Python получает SIGSEGV при загрузке написанного модуля расширения C ++

Пример правильного кода:

#include "Python.h"#include <string>

extern const int someConstant;

void some_function()
{
const char *begin = NULL;
const char *end = NULL;

std::string s(begin, end);
const int v = someConstant;
}

static PyMethodDef _G_methods[] =
{
{NULL, NULL, 0, NULL}        /* Sentinel */
};

PyMODINIT_FUNC initsf()
{
PyObject *module;

if (!(module = Py_InitModule("sf", _G_methods)))
{
return;
}

PyObject *pyerror = PyErr_NewException("fs.error", NULL, NULL);
Py_INCREF(pyerror);PyModule_AddObject(module, "error", pyerror);
}

Это проект модуля расширения. Как можно проще. Он имеет пустую таблицу методов и функцию инициализатора, скопированную из оригинала docpage. Содержит 2 (две) преднамеренные ошибки:

  • переменная someConstant объявлена, но никогда не определена;

  • функция some_function определена, но никогда не вызывается;

Если скомпилировано и открыто dlopen / dlsym:

sf.so: undefined symbol: someConstant

как требуется. Но если загружен интерпретатором Python:

>>> from sf import *
Segmentation fault (core dumped)

и самое странное — обратная трассировка Python, сброшенная из core-файла:

#0  0x00000bd6 in ?? ()
#1  0xb775c057 in char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) () from /usr/local/lib/python2.7/dist-packages/sf.so
#2  0xb6f9abb6 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) () from /usr/lib/i386-linux-gnu/libstdc++.so.6
#3  0xb6c3fe30 in pkgInitConfig(Configuration&) () from /usr/lib/i386-linux-gnu/libapt-pkg.so.4.12
#4  0xb6cf959e in ?? () from /usr/lib/python2.7/dist-packages/apt_pkg.so
#5  0x081949c1 in PyEval_EvalFrameEx ()
#6  0x0819af70 in PyEval_EvalCodeEx ()
#7  0x0819bb03 in PyImport_ExecCodeModuleEx ()
#8  0x0814bd40 in ?? ()
#9  0x080a38c2 in ?? ()
#10 0x0814c6d4 in ?? ()
#11 0x081031ae in ?? ()
...

Кажется, загрузчик Python вызывает конструктор std :: string :-).

Итак, стек поврежден. Это происходит либо при загрузке недопустимого модуля, либо при его выгрузке после обработки ошибки. Этого никогда не произойдет, если пример кода мало изменился. Такое поведение наблюдается в Python 2.7.3 / Linux Ubuntu 10 / gcc 4.6.3 и определенно не показано в Python 2.7.1 / FreeBSD 8.1 / gcc 4.2.1.

Вопрос:

  1. Это ошибка Python или мой пример кода содержит ошибки?

5

Решение

Давайте снова посмотрим на эту трассировку стека

# 0 0x00000bd6 в ?? ()
# 1 0xb775c057 в char * std :: string :: _ S_construct<символ const *>(char const *, char const *, std :: allocator<голец> Const&, std :: forward_iterator_tag) () из /usr/local/lib/python2.7/dist-packages/sf.so
# 2 0xb6f9abb6 в std :: basic_string<char, std :: char_traits<голец>, std :: allocator<голец> >:: basic_string (char const *, std :: allocator<голец> Const&) () из /usr/lib/i386-linux-gnu/libstdc++.so.6
# 3 0xb6c3fe30 в pkgInitConfig (Конфигурация&) () из /usr/lib/i386-linux-gnu/libapt-pkg.so.4.12
# 4 0xb6cf959e в ?? () из /usr/lib/python2.7/dist-packages/apt_pkg.so

Так что функция в libapt-pkg.so вызывает функцию в libstdc++.so которая вызывает функцию в вашем модуле.

Ваши функции никогда не вызывают. Тем не менее, ваш код использует std::string и создает некоторые функции для std::stringэти функции включены в ваш *.soпереопределить те, которые используются совершенно другим *.soи сбой по какой-то причине, я не совсем уверен, почему.

Мои инстинкты говорят мне, что ты использовал gcc создать свой *.so вместо g++, Вы не получите ошибку во время ссылки, потому что связывание общих объектов не работает таким образом. Вы не получите ошибку во время загрузки, потому что libstdc++ является совпадению уже загружен.

Ты используешь gcc или же g++ связывать? Попробуйте использовать g++,

2

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector