2010-11-26 5 views
15

J'utilise backtrace pour obtenir l'information à partir de laquelle l'exception est levée. Dans le constructeur de mon exception, je stocke le backtrace dans une chaîne std :: string, et dans le bloc catch pour les exceptions de ce type, j'imprime ce backtrace.Obtention du backtrace à partir du bloc catch

Mais je me demandais, est-il possible d'obtenir d'une façon ou d'une autre le même backtrace dans le bloc catch pour d'autres types d'exception?

+0

Vous voudrez peut-être jeter un oeil à travers [cet article] (http://stackoverflow.com/questions/3355683/c-stack-trace-from-unhandled-exception "c-stack-trace-from-unhandled- exception"). Cela pourrait vous rapprocher de l'endroit où vous voulez être. –

+0

Le problème avec std :: set_terminate est que le programme se terminera quand le callback sera appelé. –

Répondre

8

Je ne pense pas. Quand les executons s'arrêtent dans le bloc catch, la pile est déroulée, et tout ce qui s'est passé avant n'est plus dans la pile.

+0

Oui, exactement. Ce qui nous amène à «comment faire quelque chose quand l'exception est * lancée *» - http://stackoverflow.com/q/4223390/57428 – sharptooth

+0

Len Holgate a mentionné l'API Debug pour intercepter les exceptions exactement quand elles sont lancées. Cela semble compliqué, mais faisable. – Dialecticus

9

Vous pourriez être intéressé par une bibliothèque Boost en cours de développement: Portable Backtrace. Exemple:

#include <boost/backtrace.hpp> 
#include <iostream> 

int foo() 
{ 
    throw boost::runtime_error("My Error"); 
    return 10; 
} 

int bar() 
{ 
    return foo()+20; 
} 


int main() 
{ 
    try { 
     std::cout << bar() << std::endl; 
    } 
    catch(std::exception const &e) 
    { 
     std::cerr << e.what() << std::endl; 
     std::cerr << boost::trace(e); 
    } 
} 

Prints:

My Error 
0x403fe1: boost::stack_trace::trace(void**, int) + 0x1b in ./test_backtrace 
0x405451: boost::backtrace::backtrace(unsigned long) + 0x65 in ./test_backtrace 
0x4054d2: boost::runtime_error::runtime_error(std::string const&) + 0x32 in ./test_backtrace 
0x40417e: foo() + 0x44 in ./test_backtrace 
0x40425c: bar() + 0x9 in ./test_backtrace 
0x404271: main + 0x10 in ./test_backtrace 
0x7fd612ecd1a6: __libc_start_main + 0xe6 in /lib/libc.so.6 
0x403b39: __gxx_personality_v0 + 0x99 in ./test_backtrace 

Hope this helps!

+0

Oui, c'est exactement ce dont j'ai besoin, mais pour autant que je puisse voir, il est toujours dans la version de boost, et pour le moment je suis bloqué en boost 1.34.1 :( –

+2

Peut-être que vous pouvez le télécharger séparément et l'utiliser –

+1

Désolé, mais je me suis rendu compte que cela ne répond pas à ma question, pour cela, vous devez lancer des exceptions boost, mais le backtrace n'est pas imprimé si un autre type d'exception est attrapé –

1

Est-ce que les classes en question partagent une base commune que vous pouvez modifier?

Sinon, j'ai fourni une réponse merveilleuse mais terriblement sous-estimée à How can some code be run each time an exception is thrown in a Visual C++ program? ;-P D'autres ont également exprimé leur opinion.

+0

Mais je ne suis pas linux, donc pas de studio visuel ici;) –

+0

Oui, les cours d'exception que je lance avoir une base commune, et je peux obtenir le backtrace pour ceux. Le problème est comment obtenir le backtrace d'autres types d'exception? Par exemple std :: out_of_range –

+0

@VJo: mon hack sale n'était pas spécifique à Visual C++ (en fait, je l'ai testé uniquement dans GCC) - mais il ne convient pas non plus à une utilisation en production sérieuse. Pour std :: out_of_range, c'est un problème - devinez que cela dépend de la valeur que cela représente pour vous, mais vous pourriez explorer l'évolution de std :: exception elle-même, en utilisant des techniques de débogage. Avez-vous affaire avec std :: out_of_range et al lancés à partir de bibliothèques tierces (si oui, avez-vous même des sources), ou juste dans votre propre code? Y a-t-il trop de source pour changer les instructions throw? –

Questions connexes