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.