backtrace() 段錯誤定位

hellozhangjz發表於2024-07-09

段錯誤定位

原因是昨天遇到一個BUG,復現機率很小,一直復現了一下午,後來google發現可以用execinfo.h裡的backtrace函式及訊號處理機制, 來讓程式在發生段錯誤時自動列印呼叫堆疊。最後終於復現出來了兩次,用這個函式也定位到了出錯位置,是多執行緒下的一個同步問題。

之前遇到的BUG基本都是可復現的,用簡單的列印很快就能定位到BUG位置。對於這種不可復現的BUG在開發測試的時候最好能一直帶著backtrace函式,以最快的速度定位BUG。

#include <execinfo.h>
#define BACKTRACE_SIZE 256
void segv_handler(int sig)
{
    void *func[BACKTRACE_SIZE];
    int size;
    size = backtrace(func, BACKTRACE_SIZE);
    backtrace_symbols_fd(func, size, STDERR_FILENO);
    exit(1);
}

int main(void)
{
    int *p = NULL;
    signal(SIGSEGV, segv_handler);
    *p = 0xdeadbeef; //---------------------Line 29
    return 0;
}

程式開始的時候註冊一下SIGSEGV訊號的回撥,然後編譯的時候帶上-g。程式執行出錯的時候會以彙編的形似列印呼叫棧。形式一般是這樣:

./auto[0x400654]
/lib64/libc.so.6(+0x35250)[0x7fbbe4283250]
./auto[0x400543] //----------------出錯地址
/lib64/libc.so.6(__libc_start_main+0xf5)[0x7fbbe426fb35]
./auto[0x40057e]

前邊兩行是SIGSEGV訊號被觸發的回撥,第三行是段錯誤的位置。addr2line -e auto 0x400543可以列印出這個地址對應的程式碼位置。或者也可以用objdump -d xxx列印出來彙編然後去搜尋這個地址。
參考:https://www.cnblogs.com/lchzd8/p/15845824.html

相關文章