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

C 語言除錯技巧:顯示檔案名與行號的兩大方法(內建巨集 vs addr2line)

     編輯:關於C語言

C 語言除錯技巧:顯示檔案名與行號的兩大方法(內建巨集 vs addr2line)

快速定位錯誤發生位置是除錯核心需求。本文介紹兩種互補方法:編譯期內建巨集與執行期 addr2line 工具,屬「一起 talk C 栗子吧」系列第 125 回內容。

一、方法一:內建巨集 __FILE__、__LINE__

使用方式

printf("Error at %s:%d\n", __FILE__, __LINE__);

優點

  • 零依賴,標準 C 支援
  • 程式執行時直接輸出,無需額外工具
  • 可嵌入任意日誌/斷言/錯誤處理路徑

缺點

  • 需預先在原始碼插入,無法事後補救
  • 插入位置需人工判斷,覆蓋面有限
  • 發布版通常移除,除錯資訊遺失

二、方法二:addr2line 位址轉原始碼位置

原理

  • 編譯時加入 -g 產生 DWARF 除錯資訊
  • 執行檔發生錯誤(如 Segfault)產生 core dump,或透過 GDB 獲取指令位址
  • addr2line -e 執行檔 -f 位址 解析出函式名、檔案名、行號

實戰流程

  1. 編譯:gcc -g test.c -o test
  2. 執行並取得位址(範例手動列印函式位址):
    void func() { printf("running\n"); }
    int main() { func(); printf("func addr: %p\n", func); }
    輸出:func addr: 0x804844d
  3. 解析:
    addr2line -f -e test 0x804844d
    # 輸出:
    # func
    # /home/user/test.c:8

常用選項

選項功能
-e指定執行檔(含除錯資訊)
-f顯示函式名
-p美化輸出格式(函式 at 檔案:行)
-CC++ 符號去修飾

三、兩方法對比總結

維度內建巨集addr2line
需修改原始碼是否
需重新編譯是需 -g 編譯
適用執行中程式僅有預留點是(core dump/GDB)
適用無原始碼程式否否(需除錯符號)
執行檔體積影響無-g 增加體積
資訊豐富度檔案+行號函式+檔案+行號

四、實務建議策略

  1. 易重現錯誤:關鍵路徑預埋 __FILE__/__LINE__ 日誌,快速定位
  2. 難重現/線上事故:啟用 core dump(ulimit -c unlimited),事後用 addr2line 或 gdb 分析
  3. 發布版:保留 -g 並分離符號表(objcopy --only-keep-debug),不影響效能
  4. 自動化:結合 backtrace()/backtrace_symbols_fd() 實現程式內建堆疊追蹤

五、進階:GDB 互動式查詢

gdb ./test core.1234
(gdb) info line *0x804844d
Line 8 of "test.c" starts at address 0x804844d ...
(gdb) list *0x804844d

善用巨集與 addr2line 雙管齊下,涵蓋開發期與上線期除錯需求,是 C 系統程式工程師的必備基本功。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved