根据脚本增加params到PyEval_EvalCode

时间:2018-02-06 22:35:28

标签: python python-2.7 cpython

在以下 MCVE 中,会执行两个不同的脚本。两者都没有做任何特别的事情,第一个有空功能,第二个脚本没什么特别的。但取决于脚本PyEval_EvalCode是否递增传递的全局/本地字典。文档没有说什么。但是根据脚本,我执行后会有一个悬空字典。我什么时候必须在之后或不在时减少它们?或者我在这里缺少什么?以下C片段输出传递的字典的引用计数。

我在Windows上尝试使用标准的Python-2.7解释器。

#pragma comment(lib, "C:\\Python27\\libs\\python27.lib")
#include "C:\\Python27\\include\\Python.h"

static int execute(const char* script)
{
    PyObject* globals = PyDict_New();
    PyDict_SetItemString(globals, "__builtins__", PyEval_GetBuiltins());

    PyObject* code = Py_CompileString(script, "test", Py_file_input);
    if (!code)
    {
        PyErr_Print();
        return 0;
    }

    PyObject* result = PyEval_EvalCode((PyCodeObject*)code, globals, nullptr);
    Py_DECREF(code);

    if (!result)
    {
        PyErr_Print();
        return 0;
    }

    Py_DECREF(result);
    printf("Refcount of globals: %zd\n", globals->ob_refcnt);
    Py_DECREF(globals); // missing decref spotted by user2357112

    return 0;
}

int main()
{
    const char* script = nullptr;

    Py_Initialize();

    // First script contains a function
    script = 
        "def main():\n" \
        "    pass\n" \
        "main()\n";
    execute(script);

    // second script does nothing
    script = "12345";
    execute(script);

    Py_Finalize();
    return 0;
}

2 个答案:

答案 0 :(得分:2)

额外引用是函数自己对其全局变量dict的引用。这个参考不是您的关注,您不需要减少该参考。

您只需要执行递减计划来清算您拥有的参考资料。

答案 1 :(得分:1)

在追踪到所有内容后,我意识到有一个循环引用。该函数获取对globals字典的引用,并且该字典使该函数保持活动状态。在脚本执行后立即调用垃圾收集器可以解决问题并解决循环引用。

execute(script);
PyGC_Collect();

P.S。还记得在我的MCVE中发现缺少减量的user2357112。