Python 何时增加?
我正在开发一个C扩展,现在正处于我想要追踪内存泄漏的阶段。通过阅读Python文档,很难理解何时增加/减少Python对象的引用计数。另外,在花了几天时间尝试嵌入Python解释器(以便将扩展编译为独立程序)之后,我不得不放弃这一努力。因此,像Valgrind这样的工具在这里是无能为力的 到目前为止,通过反复试验,我了解到,例如,Python 何时增加?,python,memory-management,cpython,Python,Memory Management,Cpython,我正在开发一个C扩展,现在正处于我想要追踪内存泄漏的阶段。通过阅读Python文档,很难理解何时增加/减少Python对象的引用计数。另外,在花了几天时间尝试嵌入Python解释器(以便将扩展编译为独立程序)之后,我不得不放弃这一努力。因此,像Valgrind这样的工具在这里是无能为力的 到目前为止,通过反复试验,我了解到,例如,Py\u DECREF(Py\u None)是一件坏事。。。但这对任何常数都是真的吗?我不知道 到目前为止,我的主要困惑如下: 如果由pywhater\u New()创
Py\u DECREF(Py\u None)
是一件坏事。。。但这对任何常数都是真的吗?我不知道
到目前为止,我的主要困惑如下:
pywhater\u New()
创建的任何东西都不能超过创建它的过程,我是否必须减少refcountPy_INCREF
都需要与Py_DECREF
匹配,还是应该有一个或多个PyObject*
,我需要增加它以确保我仍然可以使用它(永远),还是减少它以确保最终它将被垃圾收集,或者两者都不需要Py_INCREF
可能会在堆上重新分配它们)其中大部分内容已在文档中介绍,其余内容将在文档中介绍您所询问的具体问题。但是,要在一个地方实现这一切:
Py\u DECREF(Py\u None)
是件坏事。。。但这对任何常数都是真的吗
更一般的规则是,对没有得到新的/被盗的引用的任何内容调用Py\u DECREF
,并且没有调用Py\u incremf
是一件坏事。由于您从未对任何可作为常量访问的对象调用Py_INCREF
,这意味着您从未对它们调用Py_DECREF
我是否必须减少由PyWhatever\u New()
对。任何返回“新引用”的内容都必须递减。按照惯例,任何以\u New
结尾的内容都应该返回一个新引用,但无论如何都应该对其进行记录(例如,请参阅)
是否每个Py_INCREF
都需要与Py_DECREF
匹配,还是应该有一个或多个
您自己代码中的数字可能不一定平衡。总数必须保持平衡,但Python本身内部存在增量和减量。例如,任何返回“新引用”的操作都已经完成了inc,而任何“窃取”引用的操作都将执行dec
通过C API在堆栈上创建的Python对象是在堆栈上还是在堆上分配的?(例如,Py_INCREF可能会在堆上重新分配它们)
无法通过堆栈上的C API创建对象。C API只有返回对象指针的函数
这些对象中的大多数是在堆上分配的。有些实际上是在静态内存中
但是你的代码无论如何都不应该在意。您从不分配或删除它们;它们在PySpam\u New
和类似的函数中被分配,并且在Py\u DECREF
将它们释放为0时,它们将被释放,因此它们在哪里对您来说并不重要
(除了可以通过全局名称访问的常量,如Py\u None
。您显然知道这些常量位于静态存储中。)
在将Python对象传递给Python代码之前,是否需要对用C代码创建的Python对象执行任何特殊操作
没有
如果Python代码比创建Python对象的C代码更有效呢
我不知道你说的“寿命”是什么意思。当任何对象都依赖于其代码时,扩展模块不会被卸载。(事实上,至少在3.8之前,您的模块可能永远不会卸载,直到关机。)
如果您只是指\u New
“返回对象的函数,那么这不是问题。要分配堆栈上的任何Python对象,您必须走得很远。在没有将对象的C数组或C字符串转换为Python对象元组或Python字节或str的情况下,无法将它们传递到Python代码中。在某些情况下,例如,您可以将指向堆栈上某个对象的指针隐藏在PyCapsule
中并传递,但这与在任何C程序中都是一样的,还有…别这样
最后,我了解到Python同时具有引用计数和垃圾收集器
垃圾收集器只是一个循环破坏者。如果有对象通过引用循环保持彼此的活动状态,则可以依赖GC。但是,如果您泄漏了对某个对象的引用,GC将永远不会清理它。每次您在文档中看到“借用”并需要该对象的生存时间超过几微秒。您可能会发现它比原始C API更易于使用。不管怎样,您读过文档了吗?因为你所问的一些问题在那里得到了直接的回答。而且,虽然我喜欢通过segfault学习,但阅读文档通常也比较容易。@abarnert我记得这些例子,但不确定我是否在本文中见过它们。我明天再读一遍。主要问题是它使用的术语是假的。例如,“借来的”对不是Python维护者的人没有任何意义。如果他们想让它对其他开发者清晰易懂,他们必须用“必须增加/递减”来描述C++。