Fwd: Floating point exception in strtod()

Brian Inglis Brian.Inglis@SystematicSw.ab.ca
Sun Apr 8 00:05:00 GMT 2018


On 2018-04-07 11:45, Ken Brown wrote:
> #include <stdio.h>
> #include <stdlib.h>
> #include <fenv.h>
> 
> int
> main ()
> {
>   /* The following number comes from /usr/share/asymptote/ode.asy.  */
>   const char *str = "121645100408832000.0";
>   char *ptr;
> 
>   feenableexcept (FE_INVALID);
>   strtod (str, &ptr);
> 
>   /* If there was an exception, the following will not get executed.  */
>   printf ("No exception.\n");
> }

Tested using an STC which runs without exceptions, then with, using strtold then
strtod, printing in decimal and hex, and previous and current exception flags:
$ gdb strtod_test
GNU gdb (GDB) (Cygwin 7.10.1-1) 7.10.1
...
Reading symbols from strtod_test...done.
(gdb) run
Starting program: .../strtod_test
[New Thread 1428.0x1278]
[New Thread 1428.0x1980]
[New Thread 1428.0xa10]
[New Thread 1428.0x2c4]
No long double exception 121645100408832000.000000 0x1.b02b930689p+56 previous 0
current 0.
No double exception 121645100408832000.000000 0x1.b02b930689p+56 previous 0
current 0.
No long double exception 121645100408832000.000000 0x1.b02b930689p+56 previous 0
current 1.

Program received signal SIGFPE, Arithmetic exception.
_strtod_l (ptr=0xffffd680, s00=<optimized out>, se=0xffffcb98, loc=<optimized out>)
    at /usr/src/debug/cygwin-2.10.0-1/newlib/libc/stdlib/strtod.c:1189
1189                            L = (Long)aadj;
(gdb) bt
#0  _strtod_l (ptr=0xffffd680, s00=<optimized out>, se=0xffffcb98,
loc=<optimized out>)
    at /usr/src/debug/cygwin-2.10.0-1/newlib/libc/stdlib/strtod.c:1189
#1  0x0000000000000000 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
(gdb) p aadj
$1 = 2529648000
(gdb) p L
$2 = -1765319296
(gdb) p y
$3 = 1131413504
(gdb) p z
$4 = 1131413504

Seems to be happening at strtod.c line 1189 conversion to Long in:
https://sourceware.org/git/?p=newlib-cygwin.git;a=blame;f=newlib/libc/stdlib/strtod.c;h=402510cdf24ee332a9fc09c6f73df06b1975a6e2;hb=4c73ad6b20378e4b74355fcdb2005f2aac489c9f#l1189
1187			if (y == z) {
1188				/* Can we stop now? */
1189				L = (Long)aadj;		!!!
1190				aadj -= L;

│0x180197380 <_strtod_l+3376>    cvttsd2si %xmm13,%eax

Looks like this was part of JJ's 2006 rebase adding DMG's special value handling.

-- 
Take care. Thanks, Brian Inglis, Calgary, Alberta, Canada



More information about the Newlib mailing list