• [^] # Re: memforget et fuite mémoire

    Posté par (site web personnel) . En réponse au journal cTypes + Rust = approfondir une relation d'amour et d'eau (fraîche). Évalué à 3.

    Premier cas :

    struct MonObjet{
    champ: UnAutreObjet// possession "stricte"
    }

    MonObjet est propriétaire de champ. Donc à la destruction de MonObject, champ sera détruit aussi.
    Et rust garantie qui rien de pointera dessus parce qu'il n'autorise pas de références qui vivent plus longtemps que MonObjet. Sauf si tu fais du unsafe (ce qui est le cas ici), rust ne sait pas. C'est à toi de savoir comment python et rust fonctionne pour rien casser

    Pour

    struct MonObjet{
    champ: &UnAutreObjet// multiples emprunts non-mutables possibles 
    }

    Déjà, c'est faux. C'est :

    struct MonObjet<'lifetime_autreobject>{
    champ: &'lifetime_autreobjectUnAutreObjet
    }

    Et ça veut dire que MonObjet, qui emprunte (a une référence vers) UnAutreObjet, ne peut pas vivre plus longtemps que UnAutreObjet. (Même règle que plus haut, mais dans l'autre sens).
    Si python garde un pointeur sur UnAutreObjet, le problème n'arrivera pas quand MonObjet est détruit mais quand UnAutreObjet (ou son propriétaire) sera détruit.

    Dans l'exemple, ma compréhension du phénomène est la suivante : le passage dans liberer_valeurretour supprime le tableau car j'ai déclaré côté Rust, la pleine possession de celui-ci.

    Tout à fait.

    pubstruct ValeurRetour{
    puba: c_int,
    pubcontenu: Vec<c_int>
    }

    Tu déclare une structure qui est propriétaire du vecteur qui est propriétaire des entiers.

    Avec let valeur_retour = Box::new(ValeurRetour{...}); tu crées une ValeurRetour dans une box et valeur_retour est propriétaire de la box (et donc ValeurRetour)
    Avec Box::into_raw( valeur_retour ), tu quittes la propriété (au profit de personne), ta box est vidé et tu récupère le pointeur sur valeur_retour.
    Avec Box::from_raw(ptr), tu reprends la propriété. À la destruction de la box, le valeur est détruite (ainsi que le contenu).

    Entre temps, niveau python tu as deux options :

    class ValeurRetour(Structure): 
     _fields_ = [ 
     ( "a", c_int ),
     ( "contenu", POINTER(c_int) )
     ] 
    malib.test_array_retour_complexe.restype = POINTER( ValeurRetour )
    # Premier cas (le bon)
    def good():
     tableau_de_rust = malib.test_array_retour_complexe(5) 
     a = r3.contents.a 
     v = r3.contents.contenu # Un pointeur vers la mémoire interne de `vec`
     print( "[PYTHON] ===>", a, [ v[i] for i in range(0,a) ] )
     # À la destruction de `tableau_de_rust`, on va appeler `__del__` qui va désallouer
     # la mémoire dans rust. On a certes encore v qui pointe vers quelque chose, mais on
     # peut plus l'utiliser, donc osef.
    # Le mauvais cas
    def bad():
     tableau_de_rust = malib.test_array_retour_complexe(5) 
     a = r3.contents.a 
     v = r3.contents.contenu # Un pointeur vers la mémoire interne de `vec`
     print( "[PYTHON] ===>", a, [ v[i] for i in range(0,a) ] )
     return v
     # À la destruction de `tableau_de_rust`, on va appeler `__del__` qui va désallouer
     # la mémoire dans rust.
     # Par contre on a v qui pointe encore vers la mémoire interne désallouée et ça va merder quand on va l'utiliser

    Matthieu Gautier|irc:starmad