在PyDict_New()和Python >= 3.10上发生分段错误。

huangapple go评论62阅读模式
英文:

Segfault on PyDict_New() and python >= 3.10

问题

我遇到了一个关于我的Python/C库的奇怪问题。在Python版本>=3.7且<3.10上一切正常运行。但在Python>=3.10上,Python脚本会导致段错误。在它上面运行gdb显示它在PyObject* ret = PyDict_New(); 处导致了段错误。

我已经搜索了Python 3.10和3.11的发布说明,但找不到相关信息(我正在搜索已删除的函数、更改的行为等)。

这是代码:

extern "C" PyObject* compute(const char* path, int b, int h, int f, int z, int m, int mf, char* output) {
    PyObject* ret = PyDict_New();
    // 一些代码
    return ret;
}

如果我完全删除代码,只保留PyDict_New(),仍然会出现段错误。

有什么想法吗?我有一种直觉,觉得我可能漏掉了一些愚蠢的东西,但找不到是什么。谢谢。

英文:

I have a weird issue with my python/c library. Everything is working fine with python >=3.7 and < python 3.10.
With python >= 3.10, the python script segfaults. running gdb on it shows that is segfaults on PyObject* ret = PyDict_New();

I've searched python 3.10 and 3.11 release notes but can't find anything related (i was searching for a removed function, changed behaviour, etc).

the code is :

extern &quot;C&quot; PyObject* compute(const char* path, int b, int h, int f, int z, int m, int mf, char* output) {
    PyObject* ret = PyDict_New();
    // some code
    return ret;
}

Segfault is also there if i remove entirely the code and just let PyDict_New()

Any idea ? I have a gut feeling that i'm missing something stupid, but can't find what.
Thanks

答案1

得分: 1

你可能使用了CDLLWinDLL,而不是PyDLL来加载这个库。在使用Python API时,需要使用PyDLL来维持全局解释器锁(GIL)。我能够在Python 3.9下使用CDLL成功加载,但在Python 3.10或3.11下却不能,这也会导致你遇到的问题,但在没有持有GIL的情况下调用Python API是未定义行为。所有这三个Python版本都可以与PyDLL正常工作。

test.cpp

#include <Python.h>

extern "C" __declspec(dllexport)
PyObject* compute() {
    PyObject* ret = PyDict_New();
    return ret;
}

test.py

import ctypes as ct

lib = ct.PyDLL('./test')
lib.compute.argtypes = ()
lib.compute.restype = ct.py_object
print(lib.compute())

输出:

{}
英文:

You probably used CDLL or WinDLL instead of PyDLL to load the library. Using the Python API requires using PyDLL to maintain a lock on the GIL (Global Interpreter Lock). I was able to load with CDLL and Python 3.9 but not 3.10 or 3.11 so that reproduces your issue, but it is undefined behavior to call Python APIs without the GIL held. All three Python versions work with PyDLL as expected.

test.cpp

#include &lt;Python.h&gt;

extern &quot;C&quot; __declspec(dllexport)
PyObject* compute() {
    PyObject* ret = PyDict_New();
    return ret;
}

test.py

import ctypes as ct

lib = ct.PyDLL(&#39;./test&#39;)
lib.compute.argtypes = ()
lib.compute.restype = ct.py_object
print(lib.compute())

Output:

{}

huangapple
  • 本文由 发表于 2023年2月23日 22:59:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/75546549.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定