Python C Api和正确处理C ++类中的内存

时间:2013-01-07 13:34:40

标签: c++ python memory-leaks python-c-api reference-counting

我想知道如何应对以下问题。在我的C ++类中,我有一个辅助的PyObject指针。

class Foo
{
     public:
     // Should I new the dictionary here in constructor?
     Foo()
     {

     }
     // Must decrease the reference count or explicitly delete the dictionary?
     ~Foo()
     {
         Py_DECREF(myDictionary);
     }

     void sync()
     {
          myDictionary = PyDict_New();
          for (int i=0; i<myInternalData.size(); i++)
          {
                  PyObject *key =  PyInt_FromLong(i);
                  PyObject *val = PyInt_FromLong(myInternalData.at(i));
                  PyDict_SetItem(dict,key,val);
                  Py_DecRef(key);
                  Py_DecRef(val);
          }
     }

     private:
     PyObject *myDictionary;
     std::vector<int> myInternalData;
}

在我的C ++代码中,myInternalData结构偶尔会更新或调整大小,我想知道如何处理python字典的正确内存分配。

我不知道如何释放与之关联的内存,或者如何正确地将其与内部std::vector保持同步,而不会破坏堆或引发内存泄漏。

Python C API有些帮助吗?我应该用PyObject_Del释放PyDict,然后再重新分配它吗?有人建议采用另一种方法吗?

1 个答案:

答案 0 :(得分:1)

我不清楚为什么你在Python中使用字典, 当您使用一组连续的整数进行索引时,从0开始。 但是:在使用它之前,您必须执行PyDict_New 创建字典。在那之后,当你重新同步时,你 应该在开始之前清除字典,使用 PyDict_Clear,而不是重新分配新的..没有别的 应该是必要的。 (如果你重新分配一个新的,就像你一样 你的代码,你应该减少旧的引用计数 一个先。但是Python方面的任何代码都引用了 旧的将继续参考旧的; PyDict_Clear是 可能是更好的解决方案。)

另外,你应该注意临时Python对象的位置 参与其中。目前,没有其他必要因为 你只在循环中使用Python(以及C)函数,和 它们不能触发C ++异常。永远改变代码 稍微,这可能不再是这种情况。作为基本规则, 我发现你应该将PyObject*包装在一个类中 析构函数调用Py_DecRef,而不是显式调用它, 由于异常,可能会错过电话。