C語(yǔ)言的那些小秘密之函數(shù)的調(diào)用關(guān)系
顯示函數(shù)的調(diào)用關(guān)系是調(diào)試器的必備功能,如果我們?cè)诔绦虻倪\(yùn)行中出現(xiàn)了崩潰的情況,通過(guò)函數(shù)的調(diào)用關(guān)系可以快速定位問題的根源,懂得函數(shù)調(diào)用關(guān)系的實(shí)現(xiàn)原理也可以擴(kuò)充自己的知識(shí)面,在沒有調(diào)試器的情況下,我們也可以自己來(lái)實(shí)現(xiàn)顯示函數(shù)的調(diào)用關(guān)系。在我們自己動(dòng)手寫backtrace函數(shù)之前,先來(lái)看看glibc提供的backtrace函數(shù)的使用。代碼如下:
本文引用地址:http://m.butianyuan.cn/article/270700.htm #include
#include
#include
#define MAX_LEVEL 4
static void call2()
{
int i = 0;
void* buffer[MAX_LEVEL] = {0};
int size=backtrace(buffer, MAX_LEVEL);
for(i = 0; i < size; i++)
{
printf("called by %pn", buffer[i]);
}
return;
}
static void call1()
{
call2();
return;
}
static void call()
{
call1();
return;
}
int main(int argc, char* argv[])
{
call();
return 0;
}
在此先講解下backtrace()函數(shù)的使用:
int backtrace(void **buffer,int size)
該函數(shù)用來(lái)獲取當(dāng)前線程的調(diào)用堆棧,獲取的信息將會(huì)被存放在buffer中,它是一個(gè)指針列表。參數(shù) size 用來(lái)指定buffer中可以保存多少個(gè)void* 元素。函數(shù)返回值是實(shí)際獲取的指針個(gè)數(shù),最大不超過(guò)size大小,在buffer中的指針實(shí)際是從堆棧中獲取的返回地址,每一個(gè)堆??蚣苡幸粋€(gè)返回地址。
接下來(lái)的任務(wù)就是編譯運(yùn)行了。
root@ubuntu:/home/shiyan# gcc -g -Wall sss.c -o p
root@ubuntu:/home/shiyan# ./p
輸出結(jié)果為:
called by 0x8048440
called by 0x804847d
called by 0x804848a
called by 0x8048497
上面的運(yùn)行結(jié)果就是調(diào)用者的地址,看起來(lái)還不是那么的直觀,我們使用addr2line工具來(lái)實(shí)現(xiàn)地址到源代碼位置的轉(zhuǎn)換。
運(yùn)行
root@ubuntu:/home/shiyan# ./p |awk '{print "addr2line "$3" -e p"}'>t.sh;. t.sh;rm -f t.sh
輸出結(jié)果為:
/home/shiyan/sss.c:12
/home/shiyan/sss.c:27
/home/shiyan/sss.c:34
/home/shiyan/sss.c:40
接下來(lái)看看在棧中數(shù)據(jù)的結(jié)構(gòu)。
c語(yǔ)言相關(guān)文章:c語(yǔ)言教程
評(píng)論