Ошибки Python C API free () после использования Py_SetPath () и Py_GetPath () - PullRequest
0 голосов
/ 06 мая 2018

Я пытаюсь понять, почему я не могу просто получить и установить путь к Python через его C API. Я использую Python3.6, на Ubuntu 17.10 с gcc версии 7.2.0. Компилируется с:

gcc pytest.c `python3-config --libs`` python3-config --includes`

#include <Python.h>

int main()
{
    Py_Initialize(); // removes error if put after Py_SetPath

    printf("setting path\n"); // prints
    Py_SetPath(L"/usr/lib/python3.6"); // Error in `./a.out': free(): invalid size: 0x00007fd5a8365030 ***
    printf("success\n"); // doesn't print
    return 0;
}

Настройка пути работает нормально, если только я не пытаюсь получить путь до этого. Если я вообще получаю путь, даже просто печатать без изменения возвращаемого значения или чего-либо еще, я получаю ошибку «двойное освобождение или повреждение».

Очень растерян. Я что-то не так делаю или это ошибка? Кто-нибудь знает обходной путь, если так?

Редактировать: Также ошибки после вызова Py_Initialize();. Обновленный код Теперь ошибки, даже если я сначала не вызываю Py_GetPath ().

Ответы [ 2 ]

0 голосов
/ 06 мая 2018

От алка, похоже, связано с этой ошибкой: https://bugs.python.org/issue31532

Вот обходной путь, который я использую. Поскольку вы не можете вызвать Py_GetPath() до Py_Initialize(), а также, по-видимому, вы не можете вызвать Py_SetPath() после Py_Initialize(), вы можете добавить или получить путь, подобный этому, после вызова Py_Initialize():

#include <Python.h>

int main()
{
    Py_Initialize();

    // get handle to python sys.path object
    PyObject *sys = PyImport_ImportModule("sys");
    PyObject *path = PyObject_GetAttrString(sys, "path");

    // make a list of paths to add to sys.path
    PyObject *newPaths = PyUnicode_Split(PyUnicode_FromWideChar(L"a:b:c", -1), PyUnicode_FromWideChar(L":", 1), -1);

    // iterate through list and add all paths
    for(int i=0; i<PyList_Size(newPaths); i++) {
        PyList_Append(path, PyList_GetItem(newPaths, i));
    }

    // print out sys.path after appends
    PyObject *newlist = PyUnicode_Join(PyUnicode_FromWideChar(L":", -1), path);
    printf("newlist = %ls\n", PyUnicode_AsWideCharString(newlist, NULL));
    return 0;
}
0 голосов
/ 06 мая 2018

[приведенный ниже ответ относится к этой версии вопроса .]

Из документов :

void Py_Initialize()

Инициализация интерпретатора Python. В приложении, внедряющем Python, это следует вызывать перед использованием любых других функций API Python / C; за исключением Py_SetProgramName(), Py_SetPythonHome() и Py_SetPath().

Но код, который вы показываете, вызывает Py_GetPath(), прежде чем он вызывает Py_Initialize();, что неявно в соответствии с вышеприведенным абзацем.

...