84 votes

Comment peut-on récupérer une trace de pile en C?

Je sais qu'il n'y a pas de fonction standard C pour faire cela. Je me demandais quelles sont les techniques pour faire cela sous Windows et * nix? (Windows XP est mon système d'exploitation le plus important pour le faire actuellement.)

Merci pour l'aide!

81voto

sanxiyn Points 2704

La glibc fournit la fonction backtrace ().

http://www.gnu.org/software/libc/manual/html_node/Backtraces.html

31voto

Tom Points 5531

Il y a backtrace(), et backtrace_symbols():

À partir de la page de man:

     #include <execinfo.h>
     #include <stdio.h>
     ...
     void* callstack[128];
     int i, frames = backtrace(callstack, 128);
     char** strs = backtrace_symbols(callstack, frames);
     for (i = 0; i < frames; ++i) {
         printf("%s\n", strs[i]);
     }
     free(strs);
     ...

Une utilisation de plus en plus pratique/de la programmation orientée objet est moyen pour enregistrer le résultat de backtrace_symbols() dans une classe d'exception constructeur. Ainsi, chaque fois que vous jetez ce type d'exception, vous avez la trace de la pile. Ensuite, il suffit de fournir une fonction pour imprimer les documents. Par exemple:


class MyException : public std::exception {

    char ** strs;
    MyException( const std::string & message ) {
         int i, frames = backtrace(callstack, 128);
         strs = backtrace_symbols(callstack, frames);
    }

    void printStackTrace() {
        for (i = 0; i 

...


try {
 jeter MyException("Oops!");
} catch ( MyException e ) {
e.printStackTrace();
}

Ta da!

Remarque: l'activation de l'optimisation des drapeaux peuvent faire l'résultant de la trace de pile inexactes. Idéalement, il faudrait utiliser cette fonctionnalité avec les indicateurs de débogage et d'optimisation des drapeaux off.

22voto

Mark Points 6505

Nous l'avons utilisé pour nos projets:

http://www.codeproject.com/threads/StackWalker.asp

Le code est un peu désordonné à mon humble avis, mais cela fonctionne bien. Windows uniquement.

22voto

Christian.K Points 18883

Pour Windows vérifier la StackWalk64() de l'API (également sur Windows 32 bits). Pour UNIX, vous devez utiliser le système d'exploitation d'origine de façon à le faire, ou de secours à glibc backtrace(), si disponible.

Notez toutefois que le fait de prendre une Stacktrace en code natif est rarement une bonne idée, non pas parce qu'il n'est pas possible, mais parce que vous êtes à l'ordinaire essayez d'atteindre quelque chose de mal.

La plupart du temps, les gens essaient d'obtenir une stacktrace, disons, d'une circonstance exceptionnelle, comme lorsqu'une exception est interceptée, une assertion échoue ou - pire et le plus mauvais de tous, lorsque vous obtenez une fatale "exception" ou signal comme une violation de segmentation.

Compte tenu de la dernière question, la plupart des Api vous demandera explicitement allouer de la mémoire ou peut le faire en interne. Le faire dans la fragilité de l'état dans lequel votre programme peut être actuellement dans, peut acutally rendre les choses encore pire. Par exemple, le rapport de crash (ou processus) ne reflète pas la cause réelle du problème, mais votre tentative a échoué à gérer).

Je suppose que vous essayez de réaliser que fatale, erreur de manipulation de chose, comme la plupart des gens semblent essayer que lorsqu'il s'agit d'obtenir une stacktrace. Si oui, je voudrais compter sur le débogueur (en cours de développement) et de laisser le processus de processus de production (ou mini-dump sur windows). Avec symbole approprié de gestion, vous devriez avoir aucun mal à déterminer la cause de l'instruction post-mortem.

4voto

Quasidart Points 61

Pour Windows, CaptureStackBackTrace() est également une option, qui nécessite moins de code de préparation de la part de l'utilisateur que StackWalk64() . (En outre, pour un scénario similaire, CaptureStackBackTrace() finissait par travailler mieux (plus fiable) que StackWalk64() .)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X