Maison > développement back-end > C++ > le corps du texte

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
376 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!

source:php.cn
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
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!