2010-06-02 2 views
1

J'ai le code Swig suivant qui a causé une fuite de mémoire. J'ai pensé que ptr n'est pas libéré correctement. Donc, j'ai fait ce qui suit:C + + - Python swig causé une fuite de mémoire! Relatif à Py_BuildValue et SWIG_NewPointerObj

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

Mais je ne suis pas très sûr si cela causera une corruption de la mémoire. Ici, Py_XDECREF (o) va diminuer le nombre de ref, ce qui peut libérer de la mémoire utilisée par l'objet "o". Mais o fait partie de la valeur de retour "résultat". Libérer "o" peut causer des données corrompues, je suppose?

J'ai essayé mon changement. Cela fonctionne bien et l'appelant (code python) voit les données attendues. Mais cela pourrait être parce que personne d'autre ne l'écrase dans cette zone de mémoire.

Alors, quelle est la bonne façon de gérer la mémoire du code ci-dessus? Je recherche les documents swig, mais ne vois pas de description très concrète.

Aidez s'il vous plaît!

Merci, xin

+1

Un problème similaire avec le code python-nfqueue-bindings se trouve ici http://git.inl.fr/cgi-bin/gitweb.cgi?p=nfqueue-bindings.git;a=blob;f=python /libnetfilter_queue_python.i;h=fa077b74d1f9a9cbc801c2ff276a98153a0a5734;hb=09b4ad6092195d5f59b713e26ea61e8ef9f19b7d –

+0

J'ai rencontré des problèmes de fuite de mémoire similaires avec le code SWIG python - c'est l'une des raisons pour lesquelles nous avons arrêté d'utiliser SWIG dans le projet. – Petriborg

Répondre

0

Eh bien selon le code généré automatiquement par SWIG pour fonction allouer un nouvel objet, la bonne façon doit être juste mettre le drapeau propriété Python à un, ce qui signifie: python est propriétaire ce pointeur
Cela a du sens: où d'autre new Foo() pourrait-il être désalloué? L'objet wrapper Swig le gérera.

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

Cependant, je ne vois pas pourquoi vous devez réduire le nombre de références sur o: si je me souviens bien lors du passage d'un objet à un tuple ou une liste de référence est volé.