Donc, vous voulez un stand-alone, fonction qui imprime une trace de la pile avec toutes les fonctionnalités que gdb traces de pile et que ne pas mettre fin à votre application. La réponse est d'automatiser le lancement de gdb dans un mode non-interactif pour exécuter les tâches que vous souhaitez.
Ceci est fait par l'exécution de gdb dans un enfant de processus avec fork(), et un script pour afficher un stack-trace pendant que votre application attend pour la mener à bien. Cela peut être effectué sans l'utilisation d'un core dump et sans l'abandon de la demande. J'ai appris à le faire à partir de cette question: Comment il est préférable d'appeler les gdb de programme pour imprimer c'est stacktrace?
L'exemple posté cette question n'a pas fonctionné pour moi, exactement comme c'est écrit, donc voici mon "fixe" version (j'ai couru ce sur Ubuntu 9.04).
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
void print_trace() {
char pid_buf[30];
sprintf(pid_buf, "%d", getpid());
char name_buf[512];
name_buf[readlink("/proc/self/exe", name_buf, 511)]=0;
int child_pid = fork();
if (!child_pid) {
dup2(2,1); // redirect output to stderr
fprintf(stdout,"stack trace for %s pid=%s\n",name_buf,pid_buf);
execlp("gdb", "gdb", "--batch", "-n", "-ex", "thread", "-ex", "bt", name_buf, pid_buf, NULL);
abort(); /* If gdb failed to start */
} else {
waitpid(child_pid,NULL,0);
}
}
Comme indiqué dans le référencés question, gdb offre des options supplémentaires que vous pouvez utiliser. Par exemple, à l'aide de "bt full" au lieu de "bt" génère un même rapport plus détaillé (les variables locales sont inclus dans la sortie). Les pages de manuel pour gdb sont une sorte de lumière, mais la documentation complète est disponible ici.
Depuis ceci est basé sur gdb, la sortie inclut demangled noms, line-numbers, les arguments de la fonction, et éventuellement même des variables locales. Aussi, gdb est thread-conscient, de sorte que vous devriez être en mesure d'extraire certains thread spécifique de métadonnées.
Voici un exemple du genre de traces de pile que je vois avec cette méthode.
0x00007f97e1fc2925 in waitpid () from /lib/libc.so.6
[Current thread is 0 (process 15573)]
#0 0x00007f97e1fc2925 in waitpid () from /lib/libc.so.6
#1 0x0000000000400bd5 in print_trace () at ./demo3b.cpp:496
2 0x0000000000400c09 in recursive (i=2) at ./demo3b.cpp:636
3 0x0000000000400c1a in recursive (i=1) at ./demo3b.cpp:646
4 0x0000000000400c1a in recursive (i=0) at ./demo3b.cpp:646
5 0x0000000000400c46 in main (argc=1, argv=0x7fffe3b2b5b8) at ./demo3b.cpp:70
Remarque: j'ai trouvé ceci pour être incompatible avec l'utilisation de valgrind (probablement en raison de Valgrind de l'utilisation d'une machine virtuelle). Il ne fonctionne pas lorsque vous exécutez le programme à l'intérieur d'une session gdb (ne peut pas appliquer une deuxième instance de "ptrace" à un processus).