次のような関数を使用します。
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
void print_trace() {
char pid_buf[30];
sprintf(pid_buf, "--pid=%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);
}
}
出力にprint_traceの詳細が表示されます。
他の方法はありますか?
Linuxを使用している場合、標準Cライブラリには、backtrace
という関数が含まれています。これは、フレームの戻りアドレスを配列に設定し、backtrace_symbols
という別の関数は、backtrace
からアドレスを取得し、対応する関数を検索します名前。これらは GNU C Libraryマニュアル に文書化されています。
これらは引数値、ソース行などを表示せず、呼び出しスレッドにのみ適用されます。ただし、GDBをそのように実行するよりもはるかに高速(そしておそらくそれほど安定的ではない)でなければならないので、彼らは自分たちの場所を持っています。
abort()
は単純ではありませんか?
こうすることで、フィールドで発生した場合、顧客はコアファイルを送信できます(myアプリケーションに十分に関与してデバッグを強制する多くのユーザーを知りません)。