FP exception problem?
Oleg Krivosheev
kriol@fnal.gov
Thu Jan 20 13:18:00 GMT 2000
Hi, All
glibc-2.1.2 on debian linux/ia32.
GNU C Library stable release version 2.1.2, by Roland McGrath et al.
Copyright (C) 1992, 93, 94, 95, 96, 97, 98, 99 Free Software Foundation,
Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 2.95.2 19991109 (Debian GNU/Linux).
Compiled on a Linux 2.2.12 system on 1999-12-25.
Available extensions:
GNU libio by Per Bothner
crypt add-on version 2.1 by Michael Glad and others
linuxthreads-0.8 by Xavier Leroy
BIND-4.9.7-REL
NIS(YP)/NIS+ NSS modules 0.19 by Thorsten Kukuk
NSS V1 modules 2.0.2
libthread_db work sponsored by Alpha Processor Inc
basically, i told system to send SIGFPE each time floating
point exception occurs. The question is how to distinguish
what kind of exception (invalid op, div by zero etc) caused
the signal.
tried:
1. set SIGFPE handler and ask for exception bit. Didn't
work - looks like all bits are cleared.
2. from glibc info
BSD systems provide the `SIGFPE' handler with an extra argument that
distinguishes various causes of the exception. In order to access this
argument, you must define the handler to accept two arguments, which
means you must cast it to a one-argument function type in order to
establish the handler. The GNU library does provide this extra
argument, but the value is meaningful only on operating systems that
provide the information (BSD systems and GNU systems).
ok, set 2 params handler, but second parameter is always 0.
any other ways to recover the FPE information?
if there is no written yet but design already done i could try
to write the code...
thank you
OK
------------------------------------ cut here -----------------------
#define _GNU_SOURCE
#include <math.h>
#include <fenv.h>
#include <signal.h>
#include <stdio.h>
#include <values.h>
typedef void (*sighndl)(int);
static double
divide_by_zero( const double* z ) {
double x;
x = 1.0 / (*z);
return x;
}
static double
invalid_op( const double* z ) {
double x;
x = 0.0 / (*z);
return x;
}
static double
overflow( void ) {
double x = DBL_MAX;
x = x*x;
return x;
}
void
fpe_handler( int signum, int what ) {
fprintf( stderr, "Entering fpe_handler: %d\n", what );
if ( fetestexcept( FE_INEXACT ) ) {
fprintf( stderr, "INEXACT\n" );
}
if ( fetestexcept( FE_DIVBYZERO ) ) {
fprintf( stderr, "DIVBYZERO\n" );
}
if ( fetestexcept( FE_UNDERFLOW ) ) {
fprintf( stderr, "UNDERFLOW\n" );
}
if ( fetestexcept( FE_OVERFLOW ) ) {
fprintf( stderr, "OVERFLOW\n" );
}
if ( fetestexcept( FE_INVALID ) ) {
fprintf( stderr, "INVALID\n" );
}
signal( SIGFPE, SIG_DFL );
}
int
main( void ) {
fenv_t fe;
double z = 0.0;
if ( signal( SIGFPE, (sighndl)fpe_handler ) == SIG_IGN ) {
signal( SIGFPE, SIG_IGN );
}
/*
setting traps for FP exceptions
*/
fegetenv( &fe );
fesetenv( FE_NOMASK_ENV );
z = invalid_op( &z );
z = divide_by_zero( &z );
/*
z = invalid_op( &z );
z = overflow();
*/
return 0;
}
More information about the Libc-alpha
mailing list