2010-09-04 4 views
21

puis-je obtenir la description d'une exception interceptée parC++ obtenir la description d'une exception pris des prises (...) bloquer

catch(...) 

bloc? quelque chose comme .what() de std :: exception.

+1

En C de 11 rethrowing de ' std :: current_exception' peut être utilisé pour obtenir le message d'exception 'what' dans le bloc catch-all: http://stackoverflow.com/a/37222762/5447906 –

Répondre

38

Il y a un truc que vous pourriez être en mesure d'utiliser:

catch(...) { 
    handle_exception(); 
} 

void handle_exception() { 
    try { 
     throw; 
    } catch (const std::exception &e) { 
     std::cout << e.what() << "\n"; 
    } catch (const int i) { 
     std::cout << i << "\n"; 
    } catch (const long l) { 
     std::cout << l << "\n"; 
    } catch (const char *p) { 
     std::cout << p << "\n"; 
    } catch (...) { 
     std::cout << "nope, sorry, I really have no clue what that is\n"; 
    } 

et ainsi de suite, pour autant de types différents que vous pensez peut-être jeté. Si vous ne savez vraiment rien sur ce qui pourrait être jeté, alors même l'avant-dernier est faux, car quelqu'un pourrait lancer un char* qui ne pointe pas vers une chaîne terminée par nul.

Généralement, c'est une mauvaise idée de lancer tout ce qui n'est pas un std::exception ou une classe dérivée. La raison std::exception existe est de permettre à tout le monde de lancer et attraper des objets avec lesquels ils peuvent faire quelque chose d'utile. Dans un programme de jouet où vous voulez juste sortir de là et ne peut même pas être dérangé pour inclure un en-tête standard, OK, peut-être jeter un int ou un littéral de chaîne. Je ne pense pas que je ferais cette partie d'une interface formelle. Toutes les exceptions que vous lancez font partie de votre interface formelle, même si vous avez oublié de les documenter.

+2

Salut; C'est une excellente réponse. J'ai cherché pendant un certain temps à trouver des preuves dans les documents de normes que c'est un comportement standard, mais j'ai été incapable d'en trouver. Savez-vous avec certitude que c'est un comportement standard? (C'est-à-dire, entrer un nouveau bloc 'try' dans un' catch (...) {} 'et réenvoyer une exception afin de déterminer son type.) – NHDaly

+1

Travailler depuis la mémoire: recherchez le texte sur la durée de vie du exception actuelle (jusqu'à ce que vous quittiez la clause catch), et l'effet d'un 'throw' sans opérande (relance l'exception actuelle). –

5

Ce bloc peut attraper un int, ou un const char *, ou quoi que ce soit. Comment le compilateur peut-il savoir comment décrire quelque chose alors qu'il n'en sait rien? Si vous souhaitez obtenir des informations sur une exception, vous devez connaître le type.

+5

" Comment le compilateur peut-il savoir comment décrire quelque chose quand il le sait? rien à ce sujet? - +1, mais en réalité, le compilateur en sait un peu plus à ce sujet. Le mécanisme d'exception doit stocker * certaines informations de type, car il doit faire correspondre l'objet d'exception avec les clauses catch. Mais la norme ne définit pas cette information ou ne permet pas d'y accéder, c'est un détail d'implémentation caché. –

+0

Cette information de type est loin d'être suffisante pour effectuer cette opération, et aucune implémentation ne pourrait changer cela. – Puppy

+1

ressemble à un défi ;-) Une extension du compilateur '__what()' qui renvoie une chaîne contenant le nom typeinfo de l'exception actuelle (facile à implémenter) suivi de plusieurs caractères décrivant sa valeur (en pratique, vous pouvez facilement mais plutôt types intégrés, et la plupart de la bibliothèque standard, et peut-être avoir des implémentations de base pour les types définis par l'utilisateur). Bien sûr, cela signifierait que le compilateur émettait un code bloaty pour chaque type pour faire sa conversion de chaîne, mais ensuite pensez combien de 'operator <<' existe déjà. Le faire pour tout, bien sûr pas possible. –

4

Si vous savez que vous ne jetez std :: exception ou sous-classes, essayez

catch(std::exception& e) {...e.what()... } 

Sinon, comme l'a écrit DeadMG, puisque vous pouvez jeter (presque) tout, vous ne pouvez pas prendre quoi que ce soit au sujet de ce que vous avez pris.

Normalement, catch (...) ne devrait être utilisé que comme dernier moyen de défense lors de l'utilisation de bibliothèques externes mal écrites ou documentées. Donc, vous devez utiliser une hiérarchie

catch(my::specialException& e) { 
     // I know what happened and can handle it 
     ... handle special case 
     } 
catch(my::otherSpecialException& e) { 
     // I know what happened and can handle it 
     ... handle other special case 
     } 
catch(std::exception& e) { 
     //I can at least do something with it 
     logger.out(e.what()); 
     } 
catch(...) { 
    // something happened that should not have 
    logger.out("oops"); 
    } 
2

Comment nous avons nos exceptions mises en œuvre est que, nous avons nos propres classes d'exception, qui sont tous dérivés de std::exception ..

Nos exceptions contiendront Message d'exception, fonction nom, nom de fichier et ligne où des exceptions sont générées. Ceux-ci sont tous utiles non seulement pour afficher les messages, mais peut également être utilisé pour la journalisation qui aide à diagnostiquer l'exception assez facilement. Ainsi, nous obtenons toute l'information sur les exceptions générées.

Rappelez-vous les exceptions sont us pour obtenir des informations sur ce qui s'est mal passé. Ainsi, chaque bit d'information aide à cet égard ..

3

Depuis C++ 11 vous pouvez capturer l'exception actuelle avec un pointeur:

std::exception_ptr p;  // default initialization is to nullptr 

try { 
     throw 7; 
} 
catch(...) 
{ 
    p = std::current_exception(); 
} 

Ce se comporte comme un pointeur intelligent; tant qu'il y a au moins un pointeur pointant vers l'objet d'exception, il n'est pas détruit.

plus tard (peut-être même dans une autre fonction), vous pouvez prendre des mesures d'une manière similaire à la réponse actuelle haut:

try { 
    if (p) 
     std::rethrow_exception(p); 
} 
catch(int x) 
{ 

} 
catch(std::exception &y) 
{ 
} 
2

Citant bobah
#include <iostream> 

#include <exception> 
#include <typeinfo> 
#include <stdexcept> 

int main() 
{ 
    try { 
     throw ...; // throw something 
    } 
    catch(...) 
    { 
     std::exception_ptr p = std::current_exception(); 
     std::clog <<(p ? p.__cxa_exception_type()->name() : "null") << std::endl; 
    } 
    return 1; 
} 
+1

Ce n'est pas standard ou portable. Il repose sur * des détails spécifiques à l'implémentation * qui diffèrent entre les compilateurs. 'std :: exception_ptr' est un pointeur partagé intelligent vers un type * unspecified *, donc il n'y a aucune garantie que' __cxa_exception_type() 'existe –

Questions connexes