2015-11-06 20 views
1

在下面的示例代碼中,我們總共有四次異常調用,但是當我們使用優化標誌(-O3)進行編譯時,我們可以看到只有一次異常調用的調試信息。所以在這四次中止調用中發生崩潰的地方,gdb總是給出具有調試信息的那個。如何知道是否有任何庫函數(中止)調用使用超過一次或不在源中?

#include <stdio.h> 
#include <stdlib.h> 

void level_aa(int a) 
{ 
     if (a == 0) 
      abort(); 
     if (a == 1) 
      abort(); 
     if (a == 2) 
      abort(); 

     abort(); 
} 

int main(int argc,char *argv[]) 
{  int D; 
     D = atoi(argv[1]); 
     printf(" Value = %d", D); 
     level_aa(D); 
     return 0; 
} 

Comiple上述代碼與優化參數(-O3)和用gdb

>gcc -g -O3 abort_crash.c -o abort 
>gdb ./abort 
(gdb)run 1 
(gdb) bt 
#0 0x00007ffff7ab2945 in *__GI_raise (sig=<optimized out>) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64 
#1 0x00007ffff7ab3f21 in *__GI_abort() at abort.c:92 
#2 0x0000000000400634 in level_aa (a=<optimized out>) at abort_crash.c:13 
#3 main (argc=<optimized out>, argv=<optimized out>) at abort_crash.c:20 
(gdb) 

運行。如果我們觀察幀2(#2),碰撞實際發生在無線9,但示出的gdb第13行。我可以理解,它是由於源代碼的優化而發生的。因爲如果使用多次,那麼gdb回溯中顯示的行號可能不正確。是否有可能知道中止呼叫是否被多次使用或者沒有看到源碼?如果我們知道該呼叫已被多次使用並進行了優化,那麼我們可以打印一條警告消息。我們是工具(內部使用gdb)提供程序,除了轉儲文件外,我們無法看到我們用戶的源代碼。

非常感謝您的幫助.. !!

+0

如果你看不到源碼有什麼用的行號? –

+0

我們只是工具提供商,並且證明了核心轉儲的回溯,我們應該確保該後援是正確的。但是由於源代碼的優化,我們不能得到確切的行數,所以我們想要給用戶打印一條警告消息。 –

+0

相關:[gdb通過指向錯誤的代碼行顯示不正確的後臺跟蹤](http://stackoverflow.com/questions/33216397/gdb-showing-incorrect-back-trace-by-pointing-at-the-wrong - 行代碼) –

回答

1

不,這是不可能的。特別是在您給出的示例中,全部路徑導致致電abort,GCC將最有可能拋棄a的所有支票並且僅生成對abort的單個呼叫。

據我所知,DWARF中的行表信息(它將地址映射爲源文件和行號)沒有任何功能可以使行號成爲一個特定的地址映射,以某些DWARF爲條件表達。因此,我的理解是,一個地址只能代表一個源代碼行,因此GCC必須爲每個地址選擇一個行號。

在你的例子中,GCC選擇了第13行,這看起來像一個明智的選擇,因爲所有先前的代碼,檢查a確實是多餘的。

要獲得更具體的後臺跟蹤的唯一方法是編譯時不進行優化,或者使用比GDB更強大的工具。

+0

尤其是中止通常被聲明爲no_return,所以gcc知道,如果事先放棄執行,則不會調用第13行中的全部中止,因此整個if ...可以真正被踢掉從編譯器中退出。 – Jens

相關問題