Why float "division-by-zero" exception wasn't caught in a function even handler was set?
I've tried to learn the signal handling in C, when found strange behaviour.
When x /= y; executed in the context of the main function the signal handler works. But when the same executed in some function (bad_func) handler is ignored however signal handler for SIGFPE is already set.Q: Why SIGFPE wasn't caught in a function by my global signal handler even _control87 was called?
(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
{
prin开发者_运维问答tf("Jumped here from: %i\n",res);
}
puts("bye");
return 0;
}
It works for me unless I compile with optimizations turned on. For example, if I compile it from the command line as cl mysigtest.cpp
, the exceptions work as expected. But if I compile it cl /O1 mysigtest.cpp
, then it does not show the exception.
The disassembled code shows the problem:
?bad_func@@YAXXZ (void __cdecl bad_func(void)):
00000000: 68 00 00 00 00 push offset ??_C@_06CKBHOFLC@hello1?$AA@
00000005: E8 00 00 00 00 call _puts
0000000A: 68 00 00 00 00 push offset ??_C@_04EEFJMNKA@bye1?$AA@
0000000F: E8 00 00 00 00 call _puts
00000014: 83 C4 08 add esp,8
00000017: C3 ret
The division has been optimized out. Try it with optimizations turned off, or change bad_func
to the following. For me, it "defeated" the optimizer:
double bad_func(double y)
{
double x = 0.;
puts("hello1");
//abort();
x /= y;
puts("bye1");
return x;
}
And change the call to it:
bad_func( 0.0 );
精彩评论