Py_Finalize()在Python中出错后崩溃

时间:2011-07-20 06:16:58

标签: python c

我正在尝试使用Py_CompileString()PyEval_EvalCode()调用一些python代码。它工作正常,但当Python代码包含错误Py_Finalize() craches。

Py_Initialize();

PyObject* code = Py_CompileString("pprint('Hello World')", "", Py_file_input);
PyObject* m = PyImport_AddModule("__main__");
PyObject* d = PyModule_GetDict(m);
Py_DECREF(m);
PyObject* r = PyEval_EvalCode(code, d, d);
Py_DECREF(d);
if (!r)
    PyErr_Print();
Py_DECREF(code);

Py_Finalize();

输出符合预期:

Traceback (most recent call last):
  File "", line 1, in <module>
NameError: name 'pprint' is no defined

但是在调用Py_Finalize()时,程序崩溃。如果我将第3行更改为

PyObject* code = Py_CompileString("print('Hello World')", "", Py_file_input);

程序运行并终止正常。这里出了什么问题?

如果我在gdb中运行程序,我会得到这个输出:

Windows:
Program received signal SIGSEGV, Segmentation fault.
0x1e01a030 in python32!PyType_IsSubtype () from C:\Windows\SysWOW64\python32.dll

Linux:
Program received signal SIGSEGV, Segmentation fault.
0xb7ef17bb in visit_decref (op=0xb78c87ec, data=0x0) at Modules/gcmodule.c:321
321     Modules/gcmodule.c: File or Directory not found.
        in Modules/gcmodule.c

3 个答案:

答案 0 :(得分:5)

此失败的实际原因并不是您过早地调用Py_DECREF。这就是你在打电话的时候!

PyImport_AddModule返回借用的引用。这意味着除非您实际控制了Py_DECREF,否则根本不允许您致电Py_INCREF(例如,通过Py_Finalize增加引用次数)。

Python将自动垃圾收集{{1}}上的模块引用。无需采取其他行动。

答案 1 :(得分:1)

if (!r) {
    PyErr_Print();
    PyErr_Clear(); 
}

将清除错误并允许您成功拨打Py_Finalize()

答案 2 :(得分:0)

好的,我现在自己发现了错误。您只能在评估代码并检查错误后调用Py_DECREF(m)。所以工作计划是这样的:

Py_Initialize();

PyObject* code = Py_CompileString("pprint('Hello World')", "", Py_file_input);
PyObject* m = PyImport_AddModule("__main__");
PyObject* d = PyModule_GetDict(m);
PyObject* r = PyEval_EvalCode(code, d, d);
Py_DECREF(d);
if (!r)
    PyErr_Print();
Py_DECREF(m);
Py_DECREF(code);

Py_Finalize();