快速定位錯誤發生位置是除錯核心需求。本文介紹兩種互補方法:編譯期內建巨集與執行期 addr2line 工具,屬「一起 talk C 栗子吧」系列第 125 回內容。
__FILE__、__LINE__printf("Error at %s:%d\n", __FILE__, __LINE__);
addr2line 位址轉原始碼位置-g 產生 DWARF 除錯資訊addr2line -e 執行檔 -f 位址 解析出函式名、檔案名、行號gcc -g test.c -o testvoid func() { printf("running\n"); }
int main() { func(); printf("func addr: %p\n", func); }
輸出:func addr: 0x804844daddr2line -f -e test 0x804844d # 輸出: # func # /home/user/test.c:8
| 選項 | 功能 |
|---|---|
-e | 指定執行檔(含除錯資訊) |
-f | 顯示函式名 |
-p | 美化輸出格式(函式 at 檔案:行) |
-C | C++ 符號去修飾 |
| 維度 | 內建巨集 | addr2line |
|---|---|---|
| 需修改原始碼 | 是 | 否 |
| 需重新編譯 | 是 | 需 -g 編譯 |
| 適用執行中程式 | 僅有預留點 | 是(core dump/GDB) |
| 適用無原始碼程式 | 否 | 否(需除錯符號) |
| 執行檔體積影響 | 無 | -g 增加體積 |
| 資訊豐富度 | 檔案+行號 | 函式+檔案+行號 |
__FILE__/__LINE__ 日誌,快速定位ulimit -c unlimited),事後用 addr2line 或 gdb 分析-g 並分離符號表(objcopy --only-keep-debug),不影響效能backtrace()/backtrace_symbols_fd() 實現程式內建堆疊追蹤gdb ./test core.1234 (gdb) info line *0x804844d Line 8 of "test.c" starts at address 0x804844d ... (gdb) list *0x804844d
善用巨集與 addr2line 雙管齊下,涵蓋開發期與上線期除錯需求,是 C 系統程式工程師的必備基本功。