Python C扩展强制内存泄漏测试:sys.gettotalrefcount无持续增长
Python C扩展内存泄漏问题分析
你的代码确实存在内存泄漏
你通过PyLong_FromLong(i)创建了一个PyLong对象,该函数返回的是新引用——按照Python C扩展的内存管理规则,你需要手动调用Py_DECREF(temp)来释放这个对象的引用。由于你没有执行释放操作,每次调用myfunc都会留下一个无法被Python垃圾回收机制回收的PyLong对象,确实会造成内存泄漏。
为什么sys.gettotalrefcount()不再增长?
sys.gettotalrefcount()的局限性导致它无法精准反映你的泄漏情况:
- 它统计的是所有活跃Python对象的引用计数总和,但Python的内存分配器会缓存已释放的内存块。后续创建对象时可能复用这些缓存块,导致引用计数的变化不直接对应内存占用的持续增长。
- 解释器内部的临时操作(比如函数调用栈上的对象、内置模块的内部状态)会影响引用计数的数值,单次调用的变化可能被其他操作抵消,无法单独体现你代码中的泄漏。
更可靠的泄漏检测方法
- tracemalloc:Python标准库模块,可追踪内存分配,通过对比不同时间点的内存快照,直接查看哪些对象未被释放。
- valgrind:系统级工具,直接检测C扩展代码中的内存泄漏(包括未释放的堆内存),是排查C扩展内存问题的首选工具之一。
- gc模块调试:启用
gc.set_debug(gc.DEBUG_LEAK)可以让垃圾回收器输出未被回收的对象信息,但注意:C扩展中未正确加入GC链表的对象,gc可能无法追踪到。
内容的提问来源于stack exchange,提问作者daniel
相关产品推荐
相关产品推荐

