各位看官們,大家好,上一回中咱們說的內置宏的例子,這一回咱們說的例子是:顯示文件名和行號。閒話休提,言歸正轉。讓我們一起talk C栗子吧!
我們在上一回中通過內置宏來顯示文件名和行號。這一回,我們介紹另外一個顯示文件名和行號的方法:使用addr2line這個工具來顯示文件名行號。
addr2line是一個調試工具,主要借助可執行文件中的調試信息,把某個地址轉換為程序中的文件名或者行號。該工具有多個選項,我們常用的選項是”e”和”f”。
例如:addr2line -e a.out 0x12345678 會顯示與0x12345678這個地址相對應的文件名和行號。 例如:addr2line -f -e a.out 0x12345678 會在原來的基礎上顯示與0x12345678這個地址相對應的函數名,當然了這兩個選項可以一起使用,這樣就可以同時顯示文件名,函數名和行號。看官們,光說不練不是我們的風格,我們舉一個實際的例子,通過代碼來說明如何使用addr2line這個工具來顯示文件名和行號。
在例子中,我們首先運行func函數,然後在主函數中顯示函數func的地址。
int main()
{
func();
printf("address of func:%p \n",func);
return 0;
}
函數func的定義如下,簡單起見,我們只在該函數中輸出一行語句,表示函數中運行。
void func()
{
printf("func is running \n");
}
我們編譯該程序,並且加入調試信息,具體的命令如下:
gcc -g Ex082_addr2line.c -o s //編譯生成名叫s的可執行文件
運行該文件,可以得到以下結果:
./s //運行該可執行文件
func is running
address of func:0x804844d //顯示了函數的地址
接著我們通過地址來查看文件名,行號和函數名,具體的命令如下:
addr2line -f -e s 0x804844d //同時使用f和e選項,注意f需要基於e來運行,所以f在e前面
func //顯示與地址0x804844d對應的函數名
/home/talk8/Ex082_addr2line.c:8 //顯示與地址0x804844d對應的文件名和行號
看官們,正文中就不寫代碼了,完成的代碼放到了我的資源中,大家可以下載使用。從代碼中可
以看到func函數位於文件中的第8行。
最後我們來對比一下這兩種顯示文件名和行號方法的優缺點:
內置宏的優點:在程序運行時就能直接顯示出文件名和行號,不需要調試和其它第三方工具。 內置宏的缺點:需要在運行的程序中提前加入內置宏,否則不會顯示文件名和行號,此外,在程序中的哪 一行添加內置宏也是頭疼的事情,這個需要依據程序的需要來添加。 addr2line工具的優點:在調試程序的時候,通過某個地址直接顯示文件名和行號(地址通常在dump文 件獲取),最重要的是我們不需要在代碼中添加任何內容。 addr2line工具的缺點:需要在編譯時使用gcc的”g”選項來加入調試信息,這會增加編譯時間並且使目標文件的變大。此外,它需要使用程序中的地址才能顯示文件名和行號,如果沒有一個有效的地址,那麼 它就無能為力了,正所謂巧婦難為無米之炊嘛。依據我的經驗來看,顯示文件名和行號主要是為快速找出程序中的錯誤。如果程序中的錯誤比較容易重現,那麼可以在程序中必要的地方提前加入內置宏,然後編譯,並且運行編譯後的程序。當重現錯誤時就會直接輸出文件名和行號。這樣就能快速定位到錯誤發生的文件和錯誤在文件中的位置。反之,如果程序中的錯誤不容易重現,那麼就可以使用addr2line這個工具了。當程序發生錯誤時,生成dump文件(杧核心轉儲文件),在該文件中找到錯誤發生時的地址,使用該工具就可以得到發生錯誤的文件和錯誤在文件中的具體位置。另外,如果沒有dump文件時,可以使用gdb進行調試,然後借助gdb的info命令查看相關函數的地址。
看官們,在實際工作中,我們寫的程序會發生各種各樣的錯誤。因此,希望大能夠自己動手熟練掌握這兩種顯示文件名和行號的方法 。並且結合我分享的經驗在不同的情況中使用不同的方法,快速地找出程序中的錯誤。
各位看官,關於顯示文件名和行號的例子咱們就說到這裡。欲知後面還有什麼例子,且聽下回分解 。