2010-08-15 3 views
5

J'ai une question concernant la désallocation de mémoire et les exceptions. lorsque j'utilise delete pour supprimer un objet créé sur le tas. Si une exception se produit avant que cette suppression soit la fuite de mémoire ou cette suppression va s'exécuter?Désallocation de mémoire et exceptions

+0

Vous voulez dire avant, pas pendant? Eh bien, il est évident que si le 'delete' ne sera pas appelé (parce que l'exception est levée avant) alors aucune mémoire n'est libérée. Si vous demandez une exception pendant la destruction, alors http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.3 – adf88

Répondre

3

Cela dépend de l'emplacement de delete. Si c'est à l'intérieur du catch qui attrape l'exception, il peut invoquer.

try { 
    f(); // throws 
} catch(...) { 
    delete p; // will delete 
} 

Si c'est après la catch qui attire l'exception et que catch ne revient pas de la fonction (à savoir permet le flux d'exécution de procéder après le bloc catch), le delete pourrait être appelé.

try { 
    f(); // throws 
} catch(...) { 
    // execution proceeds beyond catch 
} 
delete p; // will delete 

Si le delete n'est pas dans un bloc catch ou après un bloc catch qui permet l'exécution de procéder alors delete ne sera pas appeler.

try { 
    f(); // throws 
    delete p; // will not delete 
} // ... 

Comme vous pouvez l'imaginer, dans les deux premiers cas, au-dessus du delete ne sera pas invoquée s'il y a un jet avant la delete:

try { 
    f(); // throws 
} catch(...) { 
    g(); // throws 
    delete p; // will not delete 
} 
+1

Notez que les exceptions sont bonnes parce que vous n'avez pas à les attraper dans chaque fonctionner dans la pile d'appels. Ils peuvent être combattus à un niveau "extérieur". Comment libérez-vous la mémoire allouée dans les fonctions internes? Comme par exemple si la fonction f() lève une mémoire allouée d'exception. Serait-ce une bonne idée d'attraper l'exception dans f() et la mémoire libre, puis de le relancer au niveau suivant dans la pile d'appels? – NickSoft

2

Il ne sera pas appelé. C'est pourquoi vous êtes encouragé à regarder RAII. Voir Stroustrup

5

Dans le cas que vous décrivez, la mémoire va fuir.

Deux astuces pour éviter ce problème:

  • utiliser des pointeurs intelligents qui ne souffrent pas du même problème (solution préférée)
    -> le pointeur intelligent dans construit sur la pile, son destructor est donc appelé, peu importe quoi, et la suppression du contenu pointu est fourni dans le destructor

  • les instructions utilisent try/catch, et supprimer l'élément dans la déclaration de capture et

0

Nous devons aussi faire en sorte que « exception » signifie vraiment une exception C++ qui peut être capturée par try/catch. Il existe également d'autres exceptions dans le système que C++ try/catch ne peut pas détecter (par exemple, division par 0).

Dans de tels cas (au-delà de la portée des normes C++), "delete" ne sera pas exécuté non plus, sauf si ces exceptions sont interceptées et que le gestionnaire appelle explicitement "delete" de manière appropriée.

Questions connexes