Date: Fri, 24 Dec 1999 12:49:41 +0100 From: Martin Cracauer <cracauer@cons.org> To: Sheldon Hearn <sheldonh@uunet.co.za> Cc: Ben Smithurst <ben@scientia.demon.co.uk>, Bosko Milekic <bmilekic@dsuper.net>, hackers@FreeBSD.ORG Subject: Re: SIGFPE on arithmetic overflow Message-ID: <19991224124941.A88203@cons.org> In-Reply-To: <76436.946032683@axl.noc.iafrica.com>; from Sheldon Hearn on Fri, Dec 24, 1999 at 12:51:23PM %2B0200 References: <19991224103735.A649@strontium.scientia.demon.co.uk> <76436.946032683@axl.noc.iafrica.com>
next in thread | previous in thread | raw e-mail | index | archive | help
In <76436.946032683@axl.noc.iafrica.com>, Sheldon Hearn wrote: > > > On Fri, 24 Dec 1999 10:37:35 GMT, Ben Smithurst wrote: > > > > Could somebody try this piece of code on a -STABLE machine, just out of > > > curiosity...? > > > > I did, it gets SIGFPE too. > > I think this boils down to my lack of understanding of IEEE floating > point arithmetic standards. > > The following code behaves the same on every box I can find to test it > on. Although I'm surprised that the exception is INV instead of OFL, it > seems to be standard behaviour. The cast gets compiled into a fistpl instruction (surrounded by control word manipulation), which is documented to set "invalid operation", not "overflow". Not knowing Intels reason (they may be more twisted), I think this makes sense: - The "overflow" execption is thrown for real floaing point overflow, which - if it was not masked - had a meaningful result - the FPU infinity value. - The "invalid" execption is thrown in this case of "too big for target integer type" because the result is undefined and in fact not usable in any way. If the FPU would ensure that the result would be the integer that approaches the former floating point value best (INT_MAX), it could make sense to thow it into the same basket as the floating operation (although not really, since that would require an integer infinity value). Since it doesn't even attempt to, but sets the result to complete nonsense, it choses to signal a different kind of error. This also shows why running such code with execptions enabled is usually good, not bad. Turn off exceptions only when the code is know to be aware of the effects. If you port and fix such a packet, insett a test for > INT_MAX before the cast, don't kill the exceptions. That latter would make it impossible to find the next occurance of this coding error. More info on digging follows, partly repeating what you found out already: #include <stdio.h> #include <signal.h> volatile sig_atomic_t code; void handler_siginfo(int sig, siginfo_t *info, void *nix) { code = info->si_code; } int main(void) { double x; int i; struct sigaction act; act.sa_sigaction = handler_siginfo; act.sa_flags |= SA_SIGINFO; sigemptyset(&act.sa_mask); sigaction(SIGFPE, &act, NULL); code = -1; x = 1e19; i = (int)x; printf("%d\n", i); if (code != -1) fprintf(stderr, "Code: %d\n", code); return 0; } Code 7 = "Subscript out of bounds". While this is not the direct error value from the CPU (but the portable summary), you can tell that it's not an overflow. If you run th code with exceptions disabled, you can get the statusword afterward the cast, you will find that bit one "Invalid operation" has been set by the FPU. (You can't get the real status word in a signal handler because you can't access the normal program flow's state from inside the signal handler for now). If you look at the code for the cast, it looks like this: fldl -8(%ebp) fnstcw -38(%ebp) movw -38(%ebp),%ax orw $3072,%ax movw %ax,-40(%ebp) fldcw -40(%ebp) fistpl -12(%ebp) ; causes the exception fldcw -38(%ebp) ; thowns the delayed exception Intel documentation implies that fistpl throws "invalid operation", although the manuals are not clear enough and omit this kind of error from some tables of exceptions that looked complete. Martin -- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Martin Cracauer <cracauer@cons.org> http://www.cons.org/cracauer/ BSD User Group Hamburg, Germany http://www.bsdhh.org/ To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?19991224124941.A88203>