Maison > développement back-end > C++ > Pourquoi C n'utilise-t-il pas les exceptions imbriquées pour gérer les exceptions lancées par les destructeurs ?

Pourquoi C n'utilise-t-il pas les exceptions imbriquées pour gérer les exceptions lancées par les destructeurs ?

Barbara Streisand
Libérer: 2024-11-01 01:29:02
original
519 Les gens l'ont consulté

Why doesn't C   use nested exceptions to handle exceptions thrown from destructors?

Pourquoi C n'utilise-t-il pas d'exceptions imbriquées pour lancer des destructeurs ?

Comprendre le problème

Lancement d'exceptions à partir de destructeurs introduit un dilemme : que faire lorsqu'une exception est déjà en cours ? L'écrasement de l'exception existante ou l'imbrication de la nouvelle exception dans celle existante sont des solutions potentielles, mais il a été décidé que terminer avec std::terminate serait l'approche standard.

Considération des exceptions imbriquées

C 11 a introduit la fonctionnalité std::nested_exception, qui pourrait potentiellement résoudre le problème en imbriquant l'ancienne exception dans la nouvelle. Cependant, cette idée n'a pas été mise en œuvre.

Raisons de la non-implémentation

Une raison pour ne pas utiliser les exceptions imbriquées dans ce contexte est le fait que std::nested_exception a utilisation très limitée, avec une seule application pratique connue : la création de piles d'appels entièrement annotées.

Cet exemple montre comment l'imbrication des exceptions fournit un moyen pratique d'ajouter du contexte et d'identifier les erreurs lors du débogage :

<code class="cpp">#include <iostream>
#include <sstream>
#include <exception>

void rethrow(const std::string& context, ...) {
    std::ostringstream ss;
    ss << context;
    auto sep = " : ";
    (void) ((ss << sep << args), sep = ", ", 0)...);
    try {
        std::rethrow_exception(std::current_exception());
    } catch(const std::invalid_argument& e) {
        std::throw_with_nested(std::invalid_argument(ss.str()));
    } catch(const std::logic_error& e) {
        std::throw_with_nested(std::logic_error(ss.str()));
    } catch(...) {
        std::throw_with_nested(std::runtime_error(ss.str()));
    }
}

int main() {
    try {
        outer("xyz");
        outer("abcd");
    } catch(std::exception& e) {
        print_exception(e);
    }
    return 0;
}

void print_exception(const std::exception& e, std::size_t depth = 0) {
    std::cerr << "exception: " << std::string(depth, ' ') << e.what() << '\n';
    try {
        std::rethrow_if_nested(e);
    } catch (const std::exception& nested) {
        print_exception(nested, depth + 1);
    }
}</code>
Copier après la connexion

Résultat attendu :

exception: outer : abcd
exception:  inner : abcdabcd
exception:   really_inner
exception:    too long
Copier après la connexion

L'exemple ci-dessus présente l'imbrication des exceptions et démontre comment cette technique aide à tracer les erreurs et à comprendre les piles d'appels.

Malgré l'utilité des exceptions imbriquées dans ce Dans un scénario spécifique, la décision de ne pas les utiliser dans le contexte des exceptions de destructeur a probablement été prise en raison de la facilité et de la fiabilité de la terminaison avec std::terminate.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal