2011-06-26 43 views
2

我有一個ç程序與多行宏和宏內的程序崩潰,我怎麼能找準宏觀在崩潰發生中的位置調試C預處理器宏內崩潰使用gdb

這裏是我的程序的簡化版本。實際上,CRASHES是多行,不容易手動擴展。

#include <stdio.h> 
#include <stdarg.h> 
#define CRASHES(ptr) \ 
    (*(ptr) == 123) 
main() 
{ 
    char *foo = NULL; 
    if (CRASHES(foo)) 
     printf("This will never happen."); 
} 

當編譯,並與gdb a.out運行此我得到預期的EXC_BAD_ACCESS(我是Mac OS X上使用gdb 6.3),但飛機墜毀點,8號線,而不是4號線在崩潰實際上造成的。

我已經嘗試過用額外的調試標誌-gdwarf-2-g3編譯程序由docs的建議和宏本身中插入幾個assert()秒。不幸的是,沒有提供更多的信息。

+2

爲什麼應該是第4行?該崩潰位於第8行,宏被擴展和使用。這個宏本身並沒有導致段錯誤,這是因爲foo的值,在這種情況下,所以它是正確的,崩潰位於第8行。如果它指向4將是誤導。 – ShinTakezou

回答

8

大量有價值的信息here關於宏觀調試。

...另一種方法是使用預處理器,即使用-E進行編譯並將擴展宏複製粘貼到src代碼中,然後查看是否可以從那裏進行調試。

+1

該鏈接看起來相當不錯。在過去,我使用編譯器參數擴展了宏文本,然後編譯該文件並對其進行調試。查看(g)cc的-E選項。 –

+0

不幸的是,'info macro ...'等產生'GDB沒有該代碼的預處理器宏信息,即使使用指定標誌進行編譯。但是用-E編譯並粘貼回來,我只希望GDB能爲我做到這一點。 :) – Torsten

+0

@Torsten很高興你解決了它! –

0

我有什麼辦法可以將其轉換爲實際功能?這是宏的巨大禍害之一。

+0

有時很難將某些東西轉換爲函數調用(例如http://www.google.com/codesearch#XcaBTDeweEI/src/mpid/common/datatype/dataloop/veccpy.h&type=cs - 它是以宏以獲得性能,而不是重複代碼的各種類型) – osgx

+0

不幸的是不容易。第一個宏多次擴展引用局部變量的另一個宏。 *編輯:*它實際上與引用的代碼osgx非常相似。 – Torsten

+0

夠公平的。雖然宏的性能參數已過時。大多數現代編譯器都足夠智能,可以自動內聯小到足以定義爲宏的函數。訪問局部變量是一個很好的參數,這就是爲什麼我喜歡使用匿名和/或嵌套函數的新語言。 。 。也許我們會在某一天看到c/C++。哈哈,jk。 – jpm

0

你不說什麼關於如何它崩潰。如果它是段錯誤,請注意,它可能會比實際解除引用錯誤指針值時晚一點。

1

當然,這是因爲你正在引用NULL指針而崩潰......(這不是這個問題吧?)。有了這個特殊的例子,很容易:GCC -g2和gdb說

Program received signal SIGSEGV, Segmentation fault. 
0x080483d9 in main() at crash.c:10 
10  if (CRASHES(foo)) 

這是相當明確的,你自己的宏擴展,看看爲什麼(因爲* foo的== 123個存取存儲器,你不能讀,因爲foo是NULL)。在更復雜的情況下,gcc -E可以幫助或避免使用宏。