Py_Finalize () падает после ошибки в Python

1

Я пытаюсь вызвать некоторый код python, используя Py_CompileString() и PyEval_EvalCode(). Он отлично работает, но когда код Python содержит ошибку Py_Finalize() судороги.

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
    Почему вы не проверяете результат каждого шага?
  • 0
    Я не проверял, потому что думал, что m & d не изменится, потому что у них нет связи с кодом. И это правда: ни один из них не возвращает ошибку.
Теги:

3 ответа

5
Лучший ответ

Фактическая причина этого не в том, что вы слишком рано вызываете Py_DECREF. Это то, что вы звоните вообще!

PyImport_AddModule возвращает заимствованную ссылку. Это означает, что вам не разрешено Py_DECREF вызывать Py_DECREF если вы на самом деле не взяли на себя контроль над ним (например, увеличив счетчик ссылок через Py_INCREF).

Python автоматически Py_Finalize ссылки на модуль Py_Finalize. Никаких дополнительных действий не требуется.

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

Py_Finalize() ошибку и позволит вам успешно вызвать Py_Finalize().

  • 0
    Нет код все равно вылетает.
  • 0
    Что произойдет, если вы добавите PyErr_Print(0); в строке после PyErr_Print(); ? Если это не сработает, пожалуйста, отредактируйте свое сообщение, чтобы предоставить фактическую информацию о сбое.
Показать ещё 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();

Ещё вопросы

Сообщество Overcoder
Наверх
Меню