c/c++开发分享我应该在Python C Extension中将Py_INCREF和Py_DECREF放在哪个块上?

每当我调用我的函数时,每个调用的内存使用量增加大约+ 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放在我的函数上?

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

    原因是所有权规则 :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); 

    这将使程序做正确的事情。

    创建对象时,其引用计数将为1,因此在此之后:

     my_item = PyInt_FromLong(jp) 

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

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

     PyList_Append(my_list, my_item); 

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

    因此,这一行:

     PyList_Append(item, PyInt_FromLong(jp)); 

    将使用refcount 1创建一个对象并将其存储在列表中,将对象的refcount递增为2。

      以上就是c/c++开发分享我应该在Python C Extension中将Py_INCREF和Py_DECREF放在哪个块上?相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注(猴子技术宅)。

      本文来自网络收集,不代表猴子技术宅立场,如涉及侵权请点击右边联系管理员删除。

      如若转载,请注明出处:https://www.ssfiction.com/c-cyuyankaifa/545911.html

      发表评论

      电子邮件地址不会被公开。 必填项已用*标注