我应该把 Py_INCREF 和 Py_DECREF 放在 Python C 扩展中这个块的哪里?

发布于 2024-11-28 03:44:58 字数 1076 浏览 1 评论 0原文

每当我调用我的函数时,每次调用的内存使用量都会增加大约+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;
....

当我阅读 文档 时,有些调用需要

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 放在我的函数中的哪里?

Whenever I called my function, memory usage is increased around +10M per call, so I think there is some memory leak here.

....
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;
....

When I read document, some calls like

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

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

need to put reference counts like this

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);
}

So, Where should I put Py_INCREF and Py_DECREF on my function?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦在深巷 2024-12-05 03:44:58

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

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

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

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

这将使程序执行正确的操作。

The objects you create with PyInt_FromLong() and you add to the list should be kept in a local variable.

The reason are the ownership rules: PyInt_FromLong() generates a reference that you own. In the call to PyTuple_SetItem(), you lose this ownership again, because PyTuple_SetItem() "steals" it from you, so you don't have to care about. But PyList_Append() doesn't do so, it increases the refcount. In order to have the object GC'ed correctly, you have to release your ownership by DECREF'ing.

So, instead of PyList_Append(item, PyInt_FromLong(jp)), you do the following:

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

This will make the program do the right thing.

静若繁花 2024-12-05 03:44:58

创建对象时,其引用计数将为 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。

When an object is created, its refcount will be 1, so after this:

my_item  = PyInt_FromLong(jp)

the object at my_item will have a refcount of 1.

When you store an item into a container, the item's reference count is incremented so that the item will be retained, so after this:

PyList_Append(my_list, my_item);

the object at my_item will have a refcount of 2.

Therefore, this line:

PyList_Append(item, PyInt_FromLong(jp));

will create an object with refcount 1 and store it in the list, incrementing the object's refcount to 2.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文