2013-01-07 1 views
0

다음과 같은 문제에 어떻게 대처할 수 있을지 궁금합니다. 내 C++ 클래스에는 보조 PyObject 포인터가 있습니다. 내 C++ 코드 myInternalData 구조는 때때로 업데이트하거나 조정하여 내 파이썬 사전의 적절한 메모리 할당에 대처하는 방법을 알고 싶어한다에서Python C Api 및 C++ 클래스의 올바른 메모리 처리

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

.

관련 메모리를 할당 해제하는 방법이나 올바르게 힙을 손상시키지 않거나 메모리 누수를 유발하지 않고 내 내부 std::vector과 올바르게 동기화하는 방법을 모르겠습니다.

일부는 Python C API에 도움이됩니까? PyDict를 PyObject_Del으로 할당 해제했다가 다시 할당해야합니까? 다른 접근법을 제안하는 누군가? 사용하기 전에, 당신이 할 수있는 PyDict_New을해야 할 것이다 : 당신은 그러나 0 에서 시작하는 정수의 연속 세트로 색인 할 때 파이썬, 의 사전을 사용하는 이유

+0

'동기화 '를 자주 호출 하시겠습니까? 당신이 새로운 객체를 할당하고 있기 때문에 이것이 가능한 메모리 누수의 원천이라는 것을 이해할 수 있습니다. 또한 (내가 틀렸을 수도 있습니다) 사전을 할당 해제하는 적절한 방법은 ref 카운터를 0으로 줄이는 것입니다 (http://docs.python.org/2/c-api/refcounting.html). valgrind를 사용하여 mem-leaks를 어디에서 보려고 했습니까? – nvlass

답변

1

그것은 내에 명확하지 않다 사전을 만듭니다. 그런 다음 다시 동기화 할 때 은 사전에 새 사전을 할당하는 대신 PyDict_Clear을 사용하여 사전을 지워야합니다. 다른 단어는 이어야합니다. (새로 할당 한 코드를 에서 다시 할당하는 경우 이전 에서 참조 횟수를 1 줄씩 줄이십시오. 그러나 이전 코드 인 을 참조하는 Python 측의 코드는 계속해서 이전 코드를 참조합니다 하나; PyDict_Clear은 아마도 입니다.

임시 파이썬 개체 이 어디에 관련되어 있는지주의해야합니다. 루프에서 Python (및 C) 함수 만 사용하고 은 C++ 예외를 트리거 할 수 없기 때문에 현재로서는 그 외에는 아무 것도 필요하지 않습니다. 코드를 변경하여 약간, 그리고이 경우가 중지 될 수 있습니다. 일반적으로 소멸자가 Py_DecRef을 호출하고 명시 적으로 을 호출하고 예외로 인해 전화를 놓칠 수없는 클래스에 PyObject*을 래핑해야한다는 것을 발견했습니다.

+0

나는 생성자에서'PyDict_New'를 옮겼고'sync' 메소드에서는'PyDict_Clear (myDictionary)'만 호출합니다. 또한 소멸자에'Py_DECREF (myDictionary)'를 추가 했으므로 이제 모든 메모리 누수가 제거됩니다! – linello