Donnez des exemples de situations où une ré-exception peut se produire dans le contexte de l'utilisation de la construction 'double exception'.
sobes.tech IA
Réponse de l'IA
Une double exception en C++ se produit lorsque, lors du traitement d'une exception (dans le bloc catch), une nouvelle exception est levée avant que le traitement précédent ne soit terminé. Cela conduit à l'appel de std::terminate.
Exemples de situations :
-
Lancer une nouvelle exception dans un bloc
catch:#include <iostream> #include <stdexcept> void func() { throw std::runtime_error("Première exception"); } int main() { try { func(); } catch (const std::runtime_error& e) { std::cerr << "Capturé : " << e.what() << std::endl; throw std::logic_error("Deuxième exception dans catch"); // Nouvelle exception } return 0; }Ici, dans le bloc
catchqui gèrestd::runtime_error, une nouvelle exceptionstd::logic_errorest levée. -
Exception lors du nettoyage des ressources dans un destructeur dans le contexte du traitement d'une autre exception :
#include <iostream> #include <stdexcept> #include <vector> struct Resource { ~Resource() noexcept(false) { // Le destructeur peut lancer une exception std::cerr << "Destructeur de Resource appelé" << std::endl; if (true) { // Condition provoquant l'exception throw std::runtime_error("Exception dans le destructeur de Resource"); } } }; void risky_func() { Resource r; // Création d'un objet dont le destructeur peut lancer une exception throw std::runtime_error("Exception dans risky_func"); // Première exception } int main() { try { risky_func(); } catch (const std::runtime_error& e) { std::cerr << "Capturé : " << e.what() << std::endl; // Une exception peut survenir dans le destructeur 'r' pendant que nous traitons la première exception } return 0; }Lorsque
risky_funclance une exception, la pile est déroulée. Pendant ce processus, le destructeur de l'objetrest appelé. Si ce destructeur lance une exception alors que la première est en cours de traitement, une double exception se produit. -
Exception dans le gestionnaire d'exception en raison d'erreurs internes ou d'appels à des fonctions qui lancent des exceptions :
#include <iostream> #include <stdexcept> #include <vector> void process_error(const std::exception& e) { std::cerr << "Traitement de l'erreur : " << e.what() << std::endl; // Supposons que cette fonction peut lancer une exception dans certaines conditions if (e.what() && std::string(e.what()).length() > 20) { throw std::logic_error("Erreur lors du traitement d'un message trop long"); // Deuxième exception } } int main() { try { throw std::runtime_error("Ceci est un message d'erreur assez long"); // Première exception } catch (const std::exception& e) { process_error(e); // Cet appel peut lancer une deuxième exception } return 0; }Dans ce cas, la fonction
process_error, appelée dans le bloccatchpour traiter la première exception, initie une deuxième exception.
Dans tous ces scénarios, puisque la deuxième exception survient avant la fin du traitement de la première (ou pendant la déroulement de la pile en raison de la première), la norme C++ exige l'appel à std::terminate. std::terminate appelle par défaut abort().