From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 3606 invoked by alias); 2 Apr 2002 04:54:50 -0000 Mailing-List: contact gcc-help-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-help-owner@gcc.gnu.org Received: (qmail 3599 invoked from network); 2 Apr 2002 04:54:49 -0000 Received: from unknown (HELO brooklyn.lucasfilm.com) (208.244.233.2) by sources.redhat.com with SMTP; 2 Apr 2002 04:54:49 -0000 Received: from brooklyn.lucasfilm.com ([150.0.40.105]) by brooklyn.lucasfilm.com with SMTP (Microsoft Exchange Internet Mail Service Version 5.5.2653.13) id HZDT777L; Mon, 1 Apr 2002 20:54:47 -0800 Received: FROM cerberus2 BY brooklyn.lucasfilm.com ; Mon Apr 01 20:54:46 2002 -0800 Received: from lucasdigital.com (singe [10.10.96.11]) by malone.lucasdigital.com (8.8.8+Sun/8.8.8/990524-/HUB) with ESMTP id UAA17560 for ; Mon, 1 Apr 2002 20:55:59 -0800 (PST) Received: (from kainz@localhost) by singe.lucasdigital.com (SGI-8.9.3/8.8.8/990516-/CLIENT) id UAA70513 for gcc-help@gcc.gnu.org; Mon, 1 Apr 2002 20:54:42 -0800 (PST) Date: Mon, 01 Apr 2002 20:54:00 -0000 From: kainz Message-Id: <200204020454.UAA70513@singe.lucasdigital.com> To: gcc-help@gcc.gnu.org Subject: catching floating-point exceptions on GNU/Linux X-SW-Source: 2002-04/txt/msg00003.txt.bz2 Summary: I would like to handle floating-point exceptions like regular C++ exceptions, using try/catch blocks. I managed to make this work, but my method is an ugly hack. Is there a better way? Details: A large program that is currently being ported from Unix (Irix 6.5) to GNU/Linux (i686, gcc-3.0.4), requires that floating-point exceptions can be handled like regular C++ exceptions, using try/catch blocks. The following works reasonably well, as long as I don't call any of the functions defined in /usr/include/math.h: 1. Make floating-point exceptions (division by zero, overflow, invalid operand) generate SIGFPE, and install a signal handler for SIGFPE: void initFpe() { __asm__ ("fldcw %0" : : "m" (0x372)); struct sigaction sa; sa.sa_flags = SA_SIGINFO | SA_NOMASK; sa.sa_sigaction = fpeHandler; sigaction (SIGFPE, &sa, 0); } 2. In the signal handler, throw a C++ exception: void fpeHandler (int, siginfo_t*, void*) { throw "Floating-point exception"; } 3. Use try/catch blocks to handle exceptions: double f (double x) { return 1 / x; } int main () { initFpe(); try { std::cout << f(0) << '\n'; // division by zero } catch (const char *except) { std::cerr << except << '\n'; } } 4. Compile the program with g++ -funwind-tables -fnon-call-exceptions ... Unfortunately, this scheme stops working when I call functions defined in math.h. For example, when I try try { std::cout << exp (1e10); // overflow } catch (...) { // print error message } my program aborts. As far as I can tell, this happens because 1) libm is not compiled with -funwind-tables, and 2) math.h adds throw() specifications to all math functions, telling the compiler that none of those functions will ever throw any exceptions. To get around this problem, without altering libm or /usr/include/math.h, I wrote my own math.h, which, needless to say, is a rather ugly hack. My math.h looks like this (only exp() is shown; sin(), cos(), sqrt() etc. work the same way): #define exp hidden_exp #define __NO_MATH_INLINES 1 #include #undef exp extern "C++" { double exp_fpe (double x); inline double exp (double x) {return exp_fpe (x);} } The exp_fpe() function is implemented like this: #include double exp_fpe (double x) { __asm__ ("fldcw %0" : : "m" (0x37f)); // disable fpes double y = exp (x); __asm__ ("fldcw %0" : : "m" (0x372)); // enable fpes if (!finite (y)) throw "Floating-point exception"; return y; } Question: Is there a better way to do what I described above? I am porting a large program; changing the it so that it does not rely on try/catch is not an option.