我正在尝试使用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
答案 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();