Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/352.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 何时增加?_Python_Memory Management_Cpython - Fatal编程技术网

Python 何时增加?

Python 何时增加?,python,memory-management,cpython,Python,Memory Management,Cpython,我正在开发一个C扩展,现在正处于我想要追踪内存泄漏的阶段。通过阅读Python文档,很难理解何时增加/减少Python对象的引用计数。另外,在花了几天时间尝试嵌入Python解释器(以便将扩展编译为独立程序)之后,我不得不放弃这一努力。因此,像Valgrind这样的工具在这里是无能为力的 到目前为止,通过反复试验,我了解到,例如,Py\u DECREF(Py\u None)是一件坏事。。。但这对任何常数都是真的吗?我不知道 到目前为止,我的主要困惑如下: 如果由pywhater\u New()创

我正在开发一个C扩展,现在正处于我想要追踪内存泄漏的阶段。通过阅读Python文档,很难理解何时增加/减少Python对象的引用计数。另外,在花了几天时间尝试嵌入Python解释器(以便将扩展编译为独立程序)之后,我不得不放弃这一努力。因此,像Valgrind这样的工具在这里是无能为力的

到目前为止,通过反复试验,我了解到,例如,
Py\u DECREF(Py\u None)
是一件坏事。。。但这对任何常数都是真的吗?我不知道

到目前为止,我的主要困惑如下:

  • 如果由
    pywhater\u New()
    创建的任何东西都不能超过创建它的过程,我是否必须减少refcount
  • 是否每个
    Py_INCREF
    都需要与
    Py_DECREF
    匹配,还是应该有一个或多个
  • 如果对Python过程的调用导致了一个
    PyObject*
    ,我需要增加它以确保我仍然可以使用它(永远),还是减少它以确保最终它将被垃圾收集,或者两者都不需要
  • 通过C API在堆栈上创建的Python对象是在堆栈上还是在堆上分配的?(例如,
    Py_INCREF
    可能会在堆上重新分配它们)
  • 在将Python对象传递给Python代码之前,是否需要对用C代码创建的Python对象执行任何特殊操作?如果Python代码比创建Python对象的C代码更有效呢
  • 最后,我了解到Python同时具有引用计数和垃圾收集器:如果是这样的话,如果我弄乱了引用计数(即,没有足够的递减),那么它有多重要,GC最终会知道如何处理这些对象吗

  • 其中大部分内容已在文档中介绍,其余内容将在文档中介绍您所询问的具体问题。但是,要在一个地方实现这一切:

    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++。