27 votes

Pourquoi ce code n'entraîne-t-il pas une fuite de mémoire?

J'ai vérifié le code suivant en C ++ avec valgrind avec --leak-check=full et il ne dit aucune fuite de mémoire. Pourquoi donc?

 char *p = new char[256];
delete p;
 

new[] devrait être égalé par delete[] pour autant que je sache.

38voto

Jonathan Potter Points 14425

Même si c'est un comportement indéterminé comme @KillianDS dit, la différence probablement liés au fait que les deux delete et delete[] gratuit à la mémoire sous-jacente. Le point de delete[] , c'est que les destructeurs pour chaque objet du tableau sont appelés avant que la mémoire est libérée. Depuis char est un POD et ne pas avoir un destructeur, il n'est pas efficace, toute différence entre les deux dans ce cas.

Vous ne devriez pas compter sur elle, cependant.

12voto

eleforest Points 137

delete et delete[] ne seront égaux que si p pointe vers des types de données de base, tels que char ou int.

Si p pointe vers un tableau d'objets, le résultat sera différent. Essayez le code ci-dessous:

 class T {
public:
    T() { cout << "constructor" << endl; }
    ~T() { cout << "destructor" << endl; }
};

int main()
{
    const int NUM = 3;
    T* p1 = new T[NUM];

    cout << p1 << endl;
    //  delete[] p1;
    delete p1;

    T* p2 = new T[NUM];
    cout << p2 << endl;
    delete[] p2;
}
 

En utilisant delete[] tous les destructeurs de T dans le tableau seront invoqués. En utilisant delete seul le destructeur de p[0] sera invoqué.

11voto

aschepler Points 23731

Lorsque j'essaie, Valgrind rapporte:

 ==22707== Mismatched free() / delete / delete []
==22707==    at 0x4C2B59C: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==22707==    by 0x40066D: main (in /home/andrew/stackoverflow/memtest)
==22707==  Address 0x5a1a040 is 0 bytes inside a block of size 256 alloc'd
==22707==    at 0x4C2C037: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==22707==    by 0x40065D: main (in /home/andrew/stackoverflow/memtest)
 

Ce n'est pas vraiment une fuite de mémoire, mais valgrind remarque le problème.

6voto

Yu Hao Points 40603

Parce que c'est un comportement indéfini. Dans votre cas, delete peut faire le travail de delete [] dans votre compilateur, mais il peut ne pas fonctionner sur une autre machine.

1voto

Shafik Yaghmour Points 42198

C'est un comportement indéfini, donc nous ne pouvons pas raison au sujet de son comportement. Si l'on regarde le projet de norme C++ section 3.7.4.2 de Désallocation de fonctions, alinéa 3 dit: (c'est moi qui souligne):

[...] Sinon, le comportement est indéfini si la valeur fournie à l'opérateur delete(void*) dans la bibliothèque standard n'est pas l'une des valeurs retournées par un appel précédent de l'opérateur new(std::size_t) ou l'opérateur new(std::size_t, conststd::nothrow_t&) dans la bibliothèque standard, et le comportement est indéfini si la valeur fournie à l'opérateur delete[] (void*) dans la bibliothèque standard n'est pas l'une des valeurs retournées par un appel précédent de l'opérateur new[] (std::size_t) ou l'opérateur new[] (std::size_t, const std::nothrow_t&) dans le la bibliothèque standard.

Les détails réels vont être définis par l'implémentation de comportement et peut varier considérablement.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X