2010-06-23 60 views
1

我試過在C中學習信號處理,發現奇怪的行爲。
當x/= y;在信號處理程序工作的主函數的上下文中執行。但是,如果在某些函數(bad_func)處理程序中執行的處理程序被忽略,但是已經設置了SIGFPE的信號處理程序。爲什麼浮動「除零」異常沒有被捕獲到一個函數甚至處理程序被設置?

問:爲什麼SIGFPE沒有被我的全局信號處理函數捕獲到,即使_control87被調用?

(MS VC 2010):

#include "stdafx.h" 
#include <stdlib.h> 
#include <stdio.h> 
#include <signal.h> 
#include <setjmp.h> 
#include <float.h> 

jmp_buf g_jb_MainFunc; 

void hook_zd (int i) 
{ 
    printf("Result :%i\n",i); 
    longjmp(g_jb_MainFunc, 5); 
} 
void bad_func(void) 
{ 
    double x = 0., y = 0.; 
    puts("hello1"); 
    //abort(); 
    x /= y; 
    puts("bye1"); 
} 
int main(int argc, char* argv[]) 
{ 
    double x = 0., y = 0.; 
    signal(SIGFPE, hook_zd); 
    signal(SIGABRT, hook_zd); 
    puts("hello"); 
    _control87(0, _MCW_EM); 
    int res; 
    if (! (res = setjmp(g_jb_MainFunc))) 
    { 
     //abort(); 
     //x /= y; 
     bad_func(); 
    } else 
    { 
     printf("Jumped here from: %i\n",res); 
    } 
    puts("bye"); 

    return 0; 
} 
+0

'_control87'是浮點只,整數運算是一個完全不同的事情。 – GManNickG 2010-06-23 21:21:03

+0

這可能會有幫助:http://blogs.amd.com/developer/tag/mxcsr-registe/ – pmod 2010-06-23 21:40:39

+0

GMan:在Unix上設置浮點控制字也與整數除零相關。所以「浮動」名稱來自向後兼容。 – outmind 2010-06-23 22:09:35

回答

2

它爲我,除非我編譯優化開啓。例如,如果我從命令行將它編譯爲cl mysigtest.cpp,則異常按預期工作。但是如果我編譯它cl /O1 mysigtest.cpp,那麼它不會顯示異常。

的反彙編代碼示出了該問題:

[email protected]@YAXXZ (void __cdecl bad_func(void)): 
    00000000: 68 00 00 00 00  push  offset [email protected][email protected][email protected] 
    00000005: E8 00 00 00 00  call  _puts 
    0000000A: 68 00 00 00 00  push  offset [email protected][email protected][email protected] 
    0000000F: E8 00 00 00 00  call  _puts 
    00000014: 83 C4 08   add   esp,8 
    00000017: C3     ret 

劃分已被優化了。嘗試關閉優化,或將bad_func更改爲以下內容。對我來說,「擊敗」了優化:

double bad_func(double y) 
{ 
    double x = 0.; 
    puts("hello1"); 
    //abort(); 
    x /= y; 
    puts("bye1"); 
    return x; 
} 

和呼叫改變它:

bad_func(0.0); 
+0

謝謝!我會檢查它在asm級別,如果這是由於優化! – outmind 2010-06-23 21:53:05

+0

不錯!添加_fpreset()也很好。在hook_zd的longjmp之前,如果我們想在SIGFPE之後繼續執行。其他程序下次使用FPU時,程序會在我的環境中崩潰。 – outmind 2010-06-23 22:07:27