首页 > 解决方案 > python -X showrefcount 报告扩展的负引用计数

问题描述

当我在正在编写的扩展上运行带有标志的 cpython 时,当我从函数(使用宏)返回 None 时-X showrefcount,它​​会报告负引用计数(例如)。[-5538 refs, 13503 blocks]Py-RETURN_NONE

已知事实:

这是什么原因?相关问题:为什么运行空脚本后引用计数不为零?

最小的例子:

用于 cpython 调试构建的构建命令

$ ./configure --with-pydebug --with-valgrind && make

扩展名.c

#define PY_SSIZE_T_CLEAN
#include <Python.h>

static PyObject *f(void) {
    int manifest_bug = 1;
    if (manifest_bug) {
        Py_RETURN_NONE;
    }
    else {
        return PyLong_FromLong(0);
    }
}

static PyMethodDef functions[] = {
    {"f", (PyCFunction)f, METH_NOARGS, "" },
    {NULL, NULL, 0, NULL},
};

static struct PyModuleDef module = {
    PyModuleDef_HEAD_INIT,
    .m_name = "foo",
    .m_size = -1,
    .m_methods = functions,
};

PyMODINIT_FUNC PyInit_foo(void) {
    return PyModule_Create(&module);
}

安装程序.py

from setuptools import setup, Extension

name="foo"
def main() -> None:
    setup(
        name=name,
        version="0.0.0",
        ext_modules=[ Extension(name, ["extension.c"]) ],
    )

if __name__ == "__main__":
    main()

测试.py

import foo
# With fewer than roughly this many iterations, the reference count
# generally remains positive. With more iterations, it becomes more negative
for i in range(50000):
    foo.f()

标签: pythongarbage-collectioncpython

解决方案


问题是由于使用较旧版本的 python 构建的扩展,并使用从最新版本的源代码编译的调试版本运行。未使用稳定 ABI编译的扩展(并声明为这样做)在 python 版本之间不兼容二进制。

[感谢 ead 提出的直接导致此解决方案的问题的评论。]


推荐阅读