首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Linux/C 程序崩潰自動調試:信號處理 + GDB 掛載 / backtrace 獲取棧幀

     編輯:關於C語言

方案一:SIGSEGV 觸發 GDB 掛載當前進程

#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <string.h> #include <unistd.h>

void dump(int signo)
{
    char buf[1024], cmd[1024];
    FILE* fh;
    snprintf(buf, sizeof(buf), "/proc/%d/cmdline", getpid());
    if (!(fh = fopen(buf, "r"))) exit(0);
    if (!fgets(buf, sizeof(buf), fh)) { fclose(fh); exit(0); }
    fclose(fh);
    if (buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
    snprintf(cmd, sizeof(cmd), "gdb %s %d", buf, getpid());
    system(cmd);  // 彈出 GDB 交互調試
    exit(0);
}

void dummy_function(void) {
    unsigned char* ptr = 0; *ptr = 0; // 故意段錯誤
}

int main() {
    signal(SIGSEGV, dump);
    dummy_function();
    return 0;
}

優點:進入完整 GDB 環境,可查變量、回溯、設置斷點。
缺點:需部署 GDB、終端交互、不適合無人值守服務器。

方案二:信號處理器內獲取 backtrace(無依賴)

#include <execinfo.h> #include <stdio.h> #include <stdlib.h> #include <signal.h>

void dump(int signo)
{
    void* array[10];
    size_t size = backtrace(array, 10);
    char** strings = backtrace_symbols(array, size);
    printf("Obtained %zd stack frames:\n", size);
    for (size_t i = 0; i < size; ++i) printf("%s\n", strings[i]);
    free(strings);
    exit(0);
}

void dummy_function(void) {
    unsigned char* ptr = 0; *ptr = 0;
}

int main() {
    signal(SIGSEGV, dump);
    dummy_function();
    return 0;
}

編譯需鏈接 -rdynamic(導出動態符號)且 -g(調試信息):

gcc -g -rdynamic -o test test.c

輸出示例:

Obtained 5 stack frames:
./test(dummy_function+0x15) [0x4005a5]
./test(main+0x1a) [0x4005c2]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf5) [0x7f...]
./test(_start+0x2a) [0x4004da]

工程級增強建議

  1. 捕獲更多信號:SIGABRT, SIGBUS, SIGFPE, SIGILL 同註冊 dump。
  2. 異步信號安全:處理器中只能調用 async-signal-safe 函數。backtrace/backtrace_symbols/printf/malloc 不安全,但崩潰前「死馬當活馬醫」通常可接受。生產級應用用 libunwind 或寫入預分配緩衝區。
  3. 輸出到文件/日誌系統:替換 printf 為 write(STDERR_FILENO, ...) 或寫文件,避免標準輸出重定向丟失。
  4. 結合 addr2line 自動解析:addr2line -e test 0x4005a5 獲取文件行號。
  5. Google Breakpad / Crashpad:成熟跨平台崩潰收集框架,生成 minidump,支持符號化、上傳、聚類分析。

總結選型

場景推薦方案
開發機/測試環境方案一
生產服務器/嵌入式/無人值守方案二 + 寫文件 + 定期上傳
大型項目/需聚類分析Breakpad/Crashpad
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved