python -X showrefcount 报告扩展的负引用计数

python -X showrefcount reporting negative reference counts for extension

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

已知事实:

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

最小示例:

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

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

extension.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);
}

setup.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()

test.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()

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

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