2014-03-19 54 views
0

我似乎無法產生來自有意添加的算術錯誤一個核心轉儲文件在我的代碼,那就是:feenableexcept沒有產生核心轉儲

float x; 

x = 0.0/0.0; 

看來,當我創建了一個小實驗程序協同工作來測試浮點異常,但是當我在實際應用程序中實現它時,它無法產生核心轉儲。

基本上,我試圖產生一個可調試版本的版本,我在另一個文件(debuggable.c)中鏈接了一個函數,該函數使用GCC的構造函數屬性來調用feenableexcept,該函數在主要初始化之前啓用fpe異常。

debuggable.c:

void main_init(void) __attribute__((constructor)); 

void main_init(void) 
{ 
    printf("Enabling arithmetic exceptions\n"); 
    feenableexcept(fegetexcept()|FE_DIVBYZERO|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); 
}; 

然後在實際應用中的代碼,我在故意算術錯誤添加到強制核心轉儲,但它似乎並沒有工作。我已經驗證feenableexcept確實被調用,並且它返回0以表示成功基於我添加的printf語句。此外,如果使用abort()函數,則會生成核心轉儲。

看來我已經正確地配置了Linux來生成核心轉儲文件,但是有一些關於應用程序編寫或運行的方式並沒有產生核心轉儲。

我想知道如果我可能會得到什麼檢查解決這個問題的建議。

這是Red Hat Linux版本我使用:

Red Hat Enterprise Linux Client release 5.4 (Tikanga) 
5.4 RedHawk Linux (Lima) 

這裏是我的GCC版本:

gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-46) 
Copyright (C) 2006 Free Software Foundation, Inc. 

是的,我知道它老了,但我有一個遺留系統工作。

更新1

看來,當我把故意算術錯誤在真正的應用程序的功能main(),它實際上炸彈和生產的核心轉儲。它不會在main()函數的被調用函數中執行此操作,除非您將調用feenableexcept()置於被調用函數本身中。

當我在一個簡單的應用程序中測試它時,構造函數屬性技術似乎可以在被調用函數中無需調用feenableexcept()。我想知道什麼可能導致它在真正的應用程序中執行此操作?

更新2

我在幾個地方叫我在實際應用中fegetexcept(),發現它調用setjmp()後立即返回0。看來setjmp()是C標準庫的一部分,並且與longjmp()一起用於執行「非本地跳轉」。

我不確定爲什麼它將異常標誌重置爲零。我最初以爲我應該使用sigsetjmp()/siglongjmp()來保存信號,並已經調整了應用程序,但它也沒有幫助。此外,我在我的小概念驗證應用程序中測試了這一點,並且在調用setjmp()/sigsetjmp()之後,它不會將異常標誌重置爲零。我很難爲什麼setjmp()這樣做。

回答

0

我似乎無法找到所需的信息表明爲什麼異常標誌正在重置調用setjmp()longjmp()時爲零。這在我的小概念驗證程序中沒有這樣做。

我想到的一個工作是使用feholdexcept()setjmp()調用之前存儲標誌,然後再調用fesetenv()恢復標誌。這允許程序拋出異常並像平常一樣產生核心轉儲。我仍然好奇爲什麼setjmp()/longjmp()正在重置異常標誌。如果有人知道,請發佈答案。

1

我沒有測試它,但我會認爲這很可能不起作用,因爲gcc認識到你的計算在編譯時是一個常量表達式,只是將NaN賦值給x,不會觸發異常。

在其他(IEEE)的話:中恆是安靜的NaN,而不是一個信號的NaN

+0

如果這是解釋,那麼最簡潔的解決方案(如果受GCC支持)是C99的'#pragma STDC FENV_ACCESS on'。這應該防止編譯時計算'0.0/0.0'。一般來說,任何可能無法使用默認FPU標誌執行的代碼都應該使用該編譯指示進行編譯。 –

+0

@Pascal Cuoq:'#pragma STDC FENV_ACCESS on'功能似乎不被我的GCC版本所支持,因爲它會一直指示它被忽略。我也嘗試過這個[線程](http://stackoverflow.com/questions/6336786/floating-point-exceptions-gcc-bug)提供的GCC的'-frounding-math',這也沒有幫助。 –

+0

來檢查上述假設是否正確,如果可以使用非常量表達式(例如, x =(double)rand()/ 0.0; – mfro