You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

由cdef公开函数创建的PyObject*是否需手动减少引用计数?

导出Python类供C++使用的内存管理问题

背景代码

Python导出实现

class Object:
    def method(self):
        pass
    
cdef public object create_object() with gil:
    return Object()

cdef public void py_method(object obj) with gil:
    obj.method()  # 要求obj具备method()方法

生成的C头文件导出函数

__PYX_EXTERN_C PyObject *create_object(void);
__PYX_EXTERN_C void py_method(PyObject *);

核心问题

是否需要编写如下函数来避免内存泄漏?

from cpython cimport Py_XDECREF, PyObject
cdef public void destroy_object(PyObject* obj) with gil:
    Py_XDECREF(obj)

对应C++使用示例

auto obj = create_object();
py_method(obj);

// 最后释放对象
destroy_object(obj);

回答

需要编写这个destroy_object函数,理由如下:

  • create_object返回的PyObject*自带引用计数+1,C++拿到该指针后相当于持有了对象的引用,Python垃圾回收机制不会自动回收这个对象。
  • 不主动调用Py_XDECREF释放引用的话,这个Object实例会一直占用内存,最终导致内存泄漏。
  • Py_XDECREF比Py_DECREF更安全,它会先检查指针是否为NULL,避免空指针解引用引发崩溃。

另外要注意:C调用这些函数时必须处于GIL(全局解释器锁)有效的上下文,不过你写的destroy_object已经通过with gil声明,只要C调用时确保GIL是持有的(比如调用create_object和py_method时也需要GIL,嵌入Python场景下通常会先初始化并获取GIL)即可。

内容的提问来源于stack exchange,提问作者oz1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 13:55:36