isnan() causes segfault

Lev Bishop lev.bishop@gmail.com
Thu Nov 30 20:43:00 GMT 2006


On 11/30/06, Lev Bishop wrote:
> On 11/30/06, Lev Bishop wrote:
> > On 11/30/06, Eric Lilja wrote:
> > > If compiled with:
> > > $ g++ -Wall -Wextra -std=c++98 -pedantic -g isnantest.cpp -o run
> > > (those are the flags we have been using in this course).
> > > But it doesn't stackdump if compiled simply with:
> > > $ make isnantest
> > > g++     isnantest.cpp   -o isnantest
> >
> > I was able to reproduce this behaviour.
> >
> > There seems to be a difference in the generated assembler.
> > The -std=c++98 seems to be the only switch that matters.
> > Here is a diff. File isnantest2.s is the stackdumping one (ie the one
> > with -std=c++98)
>
> <snip>
>
> And the cause of the failure seems to be mutual recursion in
> /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/cmath
>
> where at line 458:
>   template<typename _Tp>
>     int
>     __capture_isnan(_Tp __f) { return isnan(__f); }
>
> which calls at line 532:
>   template<typename _Tp>
>     int
>     isnan(_Tp __f) { return __capture_isnan(__f); }
>
> which calls back to __capture_isnan().

So, the deal is that /usr/include/math.h has a macro definition for
isnan(). This is at line 138, starting with a perhaps relevant
comment:

/* Note: isinf and isnan were once functions in newlib that took double
 *       arguments.  C99 specifies that these names are reserved for macros
 *       supporting multiple floating point types.  Thus, they are
 *       now defined as macros.  Implementations of the old functions
 *       taking double arguments still exist for compatibility purposes.  */
#define isinf(x) \
          (__extension__ ({__typeof__(x) __x = (x); \
                           (sizeof (__x) == sizeof (float))  ?
__isinff(__x) : __isinfd(__x);}))
#define isnan(x) \
          (__extension__ ({__typeof__(x) __x = (x); \
                           (sizeof (__x) == sizeof (float))  ?
__isnanf(__x) : __isnand(__x);}))

So, because /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/cmath
captures this definition in it's __capture_isnan() normally things
work. However, -std=c++98 causes __STRICT_ANSI__ to be defined, and
/usr/include/math.h protects the macro definitions within a #ifndef
__STRICT_ANSI__ , things break in this situation.

It would appear that fpclassify(),  isfinite(), isinf(), isgreater(),
and others will also be affected. I'm not really clear about the
implications of this, nor what the relevant standards have to say, but
perhaps the correct thing is to change the guard at line 105 of
/usr/include/math.h to
#if !defined(__STRICT_ANSI__) ||  defined (__cplusplus)
as is done in the same file for atanf(), cosf(), et al.

Something for the newlib folks to deal with, I suppose.

Lev

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/



More information about the Cygwin mailing list