Итак, вам нужна автономная функция, которая печатает трассировку стека со всеми функциями, которые есть у трассировки стека GDB, и которая не завершает работу вашего приложения.Ответ заключается в том, чтобы автоматизировать запуск GDB в неинтерактивном режиме, чтобы выполнять только те задачи, которые вы хотите.
Это делается путем выполнения GDB в дочернем процессе с использованием fork () и сценарием его дляотображать трассировку стека, пока ваше приложение ожидает его завершения.Это может быть выполнено без использования дампа памяти и без прерывания работы приложения.Изучив этот вопрос, я узнал, как это сделать: Как лучше вызывать gdb из программы для печати его стековой трассировки?
Пример, опубликованный с этим вопросом, не работал для меня точнокак написано, вот моя «исправленная» версия (я запустил ее в 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);
}
}
Как показано в указанном вопросе, gdb предоставляет дополнительные опции, которые вы можете использовать.Например, использование «bt full» вместо «bt» создает еще более подробный отчет (локальные переменные включаются в вывод).Справочные страницы для GDB довольно просты, но полная документация доступна здесь .
Поскольку это основано на GDB, вывод включает в себя выделенные имена , номера строк , аргументы функции и, необязательно, даже локальные переменные .Кроме того, GDB поддерживает потоки, поэтому вы должны иметь возможность извлекать некоторые специфичные для потока метаданные.
Вот пример типа трассировки стека, который я вижу с помощью этого метода.
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
Примечание: я обнаружил, что это несовместимо с использованием valgrind (возможно, из-за использования виртуальной машины Valgrind).Он также не работает, когда вы запускаете программу внутри сеанса GDB (невозможно применить второй экземпляр «ptrace» к процессу).