在运行时嵌入Python的C++崩溃
我在这个问题上纠结了太久。之前我查过这个链接,一开始是有效的,但后来在某个随机的地方崩溃了。我觉得问题可能是死锁之类的。
所以,拜托,有人告诉我我哪里做错了吗:
我创建了一个全局变量:
static int gil_init = 0;
在程序开始时,我调用了
Py_Initialize()
。这个启动函数在一个会话中会被多次调用,但因为如果Python已经初始化了,Py_Initialize()
就不会做任何事情,所以我觉得这里应该没问题。在三个函数中,我多次调用Python/C API函数
py_embed(...)
(每次只有一个线程在调用)。下面的代码是在每个线程调用的py_embed()
函数中:if (!gil_init) { gil_init = 1; PyEval_InitThreads(); PyEval_SaveThread(); } state = PyGILState_Ensure(); // Call Python/C API functions... //pValue= PyObject_CallObject(pFunc, pArgs2); Crash is always given here PyGILState_Release(state);
哦,崩溃发生在其中一个函数里,但不是我第一次调用它的时候,这很奇怪。所以我才说是在运行过程中随机的地方崩溃。
理论上,根据C API的参考手册,这应该是可以工作的……我到底哪里做错了?
补充:我不调用Py_Finalize()
,是因为我遇到了这个问题。
2 个回答
0
我觉得我解决了这个问题(不能完全确定,但到现在为止没有崩溃过)。
问题在于我在使用一些借用的引用时出现了错误。我注意到这一点是因为有些对象的引用计数是2或3。
0
看看这篇文章,它帮我解决了一些线程方面的问题。特别是这部分内容:
不过,我发现这可能会导致间歇性的 死锁。看起来每个通过
PyGILState_Ensure()
使用的PyThreadState
并不是独一无二的,这导致多个线程 试图恢复同一个PyThreadState
,从而引发死锁。 解决这个问题的方法很简单,就是确保每个线程都有 自己的PyThreadState
。以下是一个部分解决方案:
// Once in each thread
m_state = PyThreadState_New(m_interpreterState);
PyEval_RestoreThread(m_state);
// Perform some Python actions here
// Release Python GIL
PyEval_SaveThread();