Je crée un objet c ++
de deux manières légèrement différentes, dans le code suivant lorsque CASE
vaut 0
il y a une fuite de mémoire, mais pas de fuite de mémoire dans le cas else
.
valgrind ./a.out ==24351== Memcheck, a memory error detector ==24351== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==24351== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info ==24351== Command: ./a.out ==24351== ==24351== ==24351== HEAP SUMMARY: ==24351== in use at exit: 32 bytes in 1 blocks ==24351== total heap usage: 2 allocs, 1 frees, 72,736 bytes allocated ==24351== ==24351== LEAK SUMMARY: ==24351== definitely lost: 32 bytes in 1 blocks ==24351== indirectly lost: 0 bytes in 0 blocks ==24351== possibly lost: 0 bytes in 0 blocks ==24351== still reachable: 0 bytes in 0 blocks ==24351== suppressed: 0 bytes in 0 blocks ==24351== Rerun with --leak-check=full to see details of leaked memory ==24351== ==24351== For counts of detected and suppressed errors, rerun with: -v ==24351== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
quand je règle CASE 0
le valgrind
dit que il y a une fuite de mémoire
#include <string> #define CASE 1 class A { private: std::string *s; public: A(std::string *p_s) { s = p_s; } }; int main() { #if CASE==0 auto a = A(new std::string("Hello")); #else auto s = std::string("Hello"); auto a = A(&s); #endif }
dans le cas contraire (ie define CASE 1
) cela fonctionne comme prévu et valgrind ne signale aucune fuite de mémoire .
Je ne suis pas capable de comprendre dans les deux cas je passe un pointeur et je ne libère pas explicitement la mémoire alors pourquoi se comportent-ils différemment?
4 Réponses :
Vous n'obtenez pas de fuite de mémoire car vous avez un pointeur.
Vous obtenez une fuite de mémoire parce que vous avez nouveau
quelque chose et ne l'avez pas supprimé
.
L'obtention d'un pointeur vers une variable de stockage automatique n'empêche pas la variable d'être nettoyée automatiquement.
En fait, tenter de supprimer & un
dans ce cas serait faux / cassé / mal / illégal / hérésie.
Ce n'est pas différent de:
// first case, leak int *j = new int (5); // // second case, no leak int q = 5; int *j = &q;
Dans le premier cas, nous avons alloué de la mémoire avec new
et il est de notre responsabilité de supprimer code> quand nous avons terminé. Dans le second cas, nous créons
q
sur la pile et il est détruit quand il est hors de portée.
La raison de ce comportement est que votre classe A
n'est pas conçue pour s'approprier std :: string *
qui lui est passé: son std :: Le membre string * s
suppose que l'objet vers lequel le pointeur est passé au constructeur serait détruit en externe.
Cela conduit à une fuite de mémoire lorsque l'objet n'est pas détruit: delete
n'est jamais appelé sur la nouvelle chaîne
passée au constructeur dans le premier cas, provoquant une fuite de mémoire .
Dans le second cas, le pointeur pointe vers une chaîne en stockage automatique. Il est détruit à la fin de main
, évitant ainsi la fuite de mémoire.
cas == 0 strud> ceci signifie que vous êtes sinon p> -> Pas de fuite de mémoire. P> p> neuf code> -ing un objet dans le tas -> Vous devez
Supprimer code> - que vous n'aviez pas dans l'extrait de la mémoire -> Fuite de la mémoire. P>
auto S = STD :: String ("Hello"); Code>: Cela signifie que vous créez un objet dans la pile et, Li>
Auto A = A (& S); Code>: Prenez son adresse (en pile, bien sûr). LI>
Dans le premier cas, vous allouez de la mémoire avec
new
, vous devez donc la libérer avecdelete
. Dans le second cas, il vous suffit de prendre un pointeur vers un objet sur la pile - pas besoin de lesupprimer
.