在运行时嵌入Python的C++崩溃

0 投票
2 回答
1211 浏览
提问于 2025-04-18 06:46

我在这个问题上纠结了太久。之前我查过这个链接,一开始是有效的,但后来在某个随机的地方崩溃了。我觉得问题可能是死锁之类的。

所以,拜托,有人告诉我我哪里做错了吗:

  1. 我创建了一个全局变量:

    static int gil_init = 0; 
    
  2. 在程序开始时,我调用了Py_Initialize()。这个启动函数在一个会话中会被多次调用,但因为如果Python已经初始化了,Py_Initialize()就不会做任何事情,所以我觉得这里应该没问题。

  3. 在三个函数中,我多次调用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();

撰写回答