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
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.
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 :
classValeurRetour(Structure):_fields_=[("a",c_int),("contenu",POINTER(c_int))]malib.test_array_retour_complexe.restype=POINTER(ValeurRetour)# Premier cas (le bon)defgood():tableau_de_rust=malib.test_array_retour_complexe(5)a=r3.contents.av=r3.contents.contenu# Un pointeur vers la mémoire interne de `vec`print("[PYTHON] ===>",a,[v[i]foriinrange(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 casdefbad():tableau_de_rust=malib.test_array_retour_complexe(5)a=r3.contents.av=r3.contents.contenu# Un pointeur vers la mémoire interne de `vec`print("[PYTHON] ===>",a,[v[i]foriinrange(0,a)])returnv# À 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
[^] # Re: memforget et fuite mémoire
Posté par GaMa (site web personnel) . En réponse au journal cTypes + Rust = approfondir une relation d'amour et d'eau (fraîche). Évalué à 3.
MonObjetest propriétaire dechamp. Donc à la destruction deMonObject,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 duunsafe(ce qui est le cas ici), rust ne sait pas. C'est à toi de savoir comment python et rust fonctionne pour rien casserPour
Déjà, c'est faux. C'est :
Et ça veut dire que
MonObjet, qui emprunte (a une référence vers)UnAutreObjet, ne peut pas vivre plus longtemps queUnAutreObjet. (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 quandMonObjetest détruit mais quandUnAutreObjet(ou son propriétaire) sera détruit.Tout à fait.
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 uneValeurRetourdans une box etvaleur_retourest propriétaire de la box (et doncValeurRetour)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 survaleur_retour.Avec
Box::from_raw(ptr), tu reprends la propriété. À la destruction de la box, le valeur est détruite (ainsi que lecontenu).Entre temps, niveau python tu as deux options :
Matthieu Gautier|irc:starmad