【问题标题】:Where should I put Py_INCREF and Py_DECREF on this block in Python C Extension?我应该将 Py_INCREF 和 Py_DECREF 放在 Python C 扩展中的这个块的哪里?
【发布时间】:2011-08-08 02:05:47
【问题描述】:

每当我调用我的函数时,每次调用的内存使用量都会增加大约 +10M,所以我认为这里存在一些内存泄漏。

....
PyObject *pair = PyTuple_New(2), *item = PyList_New(0);

PyTuple_SetItem(pair, 0, PyInt_FromLong(v[j]));

if(v[j] != DISTANCE_MAX && (p[j] || d[0][j])){
  jp=j;
  while(jp!=istart) {
    PyList_Append(item, PyInt_FromLong(jp));
    jp=p[jp];
  }

  PyList_Append(item, PyInt_FromLong(jp));

  PyList_Reverse(item);
}

PyTuple_SetItem(pair, 1, item);

return pair;
....

当我读到document 时,有些电话就像

void
bug(PyObject *list)
{
    PyObject *item = PyList_GetItem(list, 0);

    PyList_SetItem(list, 1, PyInt_FromLong(0L));
    PyObject_Print(item, stdout, 0); /* BUG! */
}

需要像这样放引用计数

void
no_bug(PyObject *list)
{
    PyObject *item = PyList_GetItem(list, 0);

    Py_INCREF(item);
    PyList_SetItem(list, 1, PyInt_FromLong(0L));
    PyObject_Print(item, stdout, 0);
    Py_DECREF(item);
}

那么,我应该将 Py_INCREF 和 Py_DECREF 放在我的函数的什么位置?

【问题讨论】:

    标签: python c reference-counting


    【解决方案1】:

    您使用 PyInt_FromLong() 创建并添加到列表中的对象应保存在局部变量中。

    原因是ownership rules:PyInt_FromLong() 生成您拥有的引用。在对 PyTuple_SetItem() 的调用中,您再次失去了此所有权,因为 PyTuple_SetItem() 从您那里“窃取”了它,因此您不必关心。但是 PyList_Append() 没有这样做,它增加了引用计数。为了正确地进行对象 GC,您必须通过 DECREF 释放您的所有权。

    因此,您可以执行以下操作,而不是 PyList_Append(item, PyInt_FromLong(jp)):

    PyObject * jpo = PyInt_FromLong(jp);
    // do some error checking here
    PyList_Append(item, jpo);
    Py_DECREF(jpo);
    

    这将使程序做正确的事。

    【讨论】:

      【解决方案2】:

      当一个对象被创建时,它的 refcount 会是 1,所以在这之后:

      my_item  = PyInt_FromLong(jp)
      

      my_item 的对象的引用计数为 1。

      当您将项目存储到容器中时,项目的引用计数会增加,以便保留该项目,因此在此之后:

      PyList_Append(my_list, my_item);
      

      my_item 处的对象的引用计数为 2。

      因此,这一行:

      PyList_Append(item, PyInt_FromLong(jp));
      

      将创建一个引用计数为 1 的对象并将其存储在列表中,将对象的引用计数增加到 2。

      【讨论】:

      • 那么......他应该把Py_INCREFPy_DECREF放在哪里?你没有回答他的问题。
      猜你喜欢
      • 1970-01-01
      • 2014-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-08
      • 1970-01-01
      • 1970-01-01
      • 2015-08-21
      相关资源
      最近更新 更多