【问题标题】:Python C API free() errors after using Py_SetPath() and Py_GetPath()使用 Py_SetPath() 和 Py_GetPath() 后的 Python C API free() 错误
【发布时间】:2018-05-06 09:09:00
【问题描述】:

我试图弄清楚为什么我不能简单地通过它的 C API 获取和设置 python 路径。我在 Ubuntu 17.10 上使用 Python3.6,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() 也会出错。

【问题讨论】:

  • 为什么要使用 C++ 编译器来编译 C 代码?这样做会使 C 代码成为 C++ 代码,从而使您的问题标记无效。
  • Python.h 是否负责包含stdio.h
  • 我不小心输入了 g++。与 gcc 的结果相同。是的Python.h 包括stdio.h
  • 您可以很好地编辑您的问题并更正任何“错别字”。
  • 大部分 Python C API 函数在Py_Initialize() 之前无法使用。文档说Py_SetPath() 可以,但他们没有说Py_GetPath() 可以在Py_Initialize() 之前调用。你有什么理由认为它可以吗?

标签: python c python-c-api


【解决方案1】:

[下面的答案指的是this version of the question。]

来自docs

void Py_Initialize()

初始化 Python 解释器。在嵌入 Python 的应用程序中,应该在使用任何其他 Python/C API 函数之前调用它; Py_SetProgramName()Py_SetPythonHome()Py_SetPath() 除外。

但是您显示的代码在调用Py_Initialize(); 之前确实调用了Py_GetPath(),根据上述段落,它不应该隐含地这样做。

【讨论】:

  • 谢谢。如果我首先调用Py_Initialize();,它会在Py_SetPath() 上正常工作而不会崩溃。虽然无论哪种方式 printf 正确输出:Py_GetPath(): /usr/lib/python36.zip:/usr/lib/python3.6:/usr/lib/python3.6:/usr/lib/python3.6/lib-dynload。编辑:没关系它仍然错误
【解决方案2】:

从 alk 看来,这似乎与此错误有关:https://bugs.python.org/issue31532

这是我正在使用的解决方法。由于在Py_Initialize()之前不能调用Py_GetPath(),在Py_Initialize()之后似乎也不能调用Py_SetPath(),所以调用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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-18
    • 2020-07-29
    • 1970-01-01
    • 2018-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多