c ++ - to-python swig вызвал утечку памяти! Связанный с Py_BuildValue и SWIG_NewPointerObj - PullRequest
1 голос
/ 02 июня 2010

У меня есть следующий код Swig, который вызвал утечку памяти.

  PyObject* FindBestMatch(const Bar& fp) {
    Foo* ptr(new Foo());
    float match;

    // call a function to fill the foo pointer

    return Py_BuildValue(
        "(fO)",
        match,
        SWIG_NewPointerObj(ptr,
                           SWIGTYPE_p_Foo,
                           0 /* own */));
  }

Я понял, что ptr не освобождается должным образом. Поэтому я сделал следующее:

  PyObject* FindBestMatch(const Bar& fp) {
    Foo* ptr(new Foo());
    float match;

    // call a function to fill the foo pointer

    *PyObject *o = SWIG_NewPointerObj(ptr,
                       SWIGTYPE_p_Foo,
                       1 /* own */);*  <------- 1 means pass the ownership to python
    PyObject *result = Py_BuildValue("(fO)", match, o);
    Py_XDECREF(o);
    return result;
  }

Но я не очень уверен, приведет ли это к повреждению памяти. Здесь Py_XDECREF (o) уменьшит количество ссылок, что может освободить память, используемую объектом «o». Но o является частью возвращаемого значения «результат». Полагаю, что освобождение "o" может привести к повреждению данных?

Я попробовал свои изменения. Он работает нормально, и вызывающая сторона (код Python) видит ожидаемые данные. Но это может быть потому, что никто не перезаписывает эту область памяти.

Так, как правильно обращаться с управлением памятью из приведенного выше кода? Я ищу документацию, но не вижу конкретного описания.

Пожалуйста, помогите!

Спасибо, * 1015 синь *

1 Ответ

0 голосов
/ 27 июня 2011

В соответствии с кодом, автоматически сгенерированным SWIG для функции, которая выделяет новый объект, правильным способом должно быть просто установить флаг владения Python равным единице, что означает: python владеет этим указателем
Это имеет смысл: где еще можно освободить ваш new Foo()? Объект-оболочка Swig справится с этим.

PyObject* FindBestMatch(const Bar& fp) {
    Foo* ptr(new Foo());
    float match;

    // call a function to fill the foo pointer

    PyObject* o = SWIG_NewPointerObj(ptr,
                   SWIGTYPE_p_Foo,
                   SWIG_BUILTIN_INIT |  0);

    PyObject* result = Py_BuildValue("(fO)", match, o);
    return result;
}

Однако я не понимаю, почему вы уменьшаете счетчик ссылок на o: если я правильно помню, когда передавал объект в кортеж или перечислял, ссылка украдена.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...