Ошибка сегментации при встраивании Python в Ubuntu - PullRequest
1 голос
/ 22 июня 2010

У меня есть приложение, в которое я встраиваю python.Он был разработан для Windows, где он работает нормально, но теперь я портирую его на Linux с меньшим успехом, когда он падает в Py_Initialize ().Из gdb, похоже, это происходит при загрузке модуля os.

gdb сообщает об этом стеке вызовов при ошибке seg:

#0  0x002384fc in import_submodule (mod=None, subname=0xb7d8a9bb "os", fullname=0xb7d8a9bb "os") at ../Python/import.c:2551
#1  0x0023893c in load_next (mod=<value optimized out>, altmod=<value optimized out>, p_name=0xb7d8a9ac, buf=0xb7d8a9bb "os", p_buflen=0xb7d8a9b4) at ../Python/import.c:2411
//.... etc...:
#65 0x002439de in Py_Initialize () at ../Python/pythonrun.c:361

исходный код import_submodule в Python / import.c (загружается из 2.6.5 python):

static PyObject *
import_submodule(PyObject *mod, char *subname, char *fullname)
{ //***************** THIS IS LINE 2551***************************
    PyObject *modules = PyImport_GetModuleDict();
    PyObject *m = NULL;

    /* Require:
       if mod == None: subname == fullname
       else: mod.__name__ + "." + subname == fullname
    */

    if ((m = PyDict_GetItemString(modules, fullname)) != NULL) {
        Py_INCREF(m);
    }
    else {
        PyObject *path, *loader = NULL;
        char buf[MAXPATHLEN+1];
        struct filedescr *fdp;
        FILE *fp = NULL;

        if (mod == Py_None)
            path = NULL;
        else {
            path = PyObject_GetAttrString(mod, "__path__");
            if (path == NULL) {
                PyErr_Clear();
                Py_INCREF(Py_None);
                return Py_None;
            }
        }

        buf[0] = '\0';
        fdp = find_module(fullname, subname, path, buf, MAXPATHLEN+1,
                  &fp, &loader);
        Py_XDECREF(path);
        if (fdp == NULL) {
            if (!PyErr_ExceptionMatches(PyExc_ImportError))
                return NULL;
            PyErr_Clear();
            Py_INCREF(Py_None);
            return Py_None;
        }
        m = load_module(fullname, fp, buf, fdp->type, loader);
        Py_XDECREF(loader);
        if (fp)
            fclose(fp);
        if (!add_submodule(mod, m, fullname, subname, modules)) {
            Py_XDECREF(m);
            m = NULL;
        }
    }

    return m;
}

Разборка + источник детали + точка останова:

2550    import_submodule(PyObject *mod, char *subname, char *fullname)
2551    {
   0x002384f0 <+0>: push   %ebp
   0x002384f1 <+1>: mov    %esp,%ebp
   0x002384f3 <+3>: sub    $0x1058,%esp
   0x002384f9 <+9>: mov    %ebx,-0xc(%ebp)
=> 0x002384fc <+12>:    call   0x174787 <__i686.get_pc_thunk.bx>
   0x00238501 <+17>:    add    $0x112af3,%ebx
   0x00238507 <+23>:    mov    %esi,-0x8(%ebp)
   0x0023850a <+26>:    mov    0x8(%ebp),%esi
   0x0023850d <+29>:    mov    %edi,-0x4(%ebp)
   0x00238510 <+32>:    mov    %eax,-0x102c(%ebp)
   0x00238516 <+38>:    mov    %edx,-0x1030(%ebp)
   0x0023851c <+44>:    mov    %gs:0x14,%eax

Что здесь происходит?Очевидно, что некоторый код из libpython2.6.so загружен и запущен.

1 Ответ

2 голосов
/ 22 июня 2010

Попробуйте установить Python дома с помощью Py_SetPythonHome, прежде чем вызывать Py_Initialize.Начните с жестко запрограммированного полного пути к каталогу python.Также убедитесь, что вы не смешиваете версии отладки и выпуска.Py_GetPath - хороший API, чтобы увидеть, где все python ищет модули - но не знаю, можно ли его вызвать до Py_Initialize.

   char pySearchPath[] = "/users/abc/Python26";
   Py_SetPythonHome(pySearchPath);
   Py_Initialize();
   PyRun_SimpleString("from time import time,ctime\n"
                     "print 'Today is',ctime(time())\n");
   cerr << Py_GetPath() << endl;
...