How to Trap Floating-Point Exceptions Using C++

Last reviewed: July 22, 1997
Article ID: Q106261
7.00 | 1.00 1.50 MS-DOS | WINDOWS WINDOWS kbprg kbcode

The information in this article applies to:

  • Microsoft C/C++ for MS-DOS, version 7.0
  • Microsoft Visual C++ for Windows, versions 1.0 and 1.5

SUMMARY

In C++, exceptions are normally handled by try catch blocks. However, Microsoft C++ versions 7.0 and 8.0 do not support the handling of floating-point exceptions. Also, because the longjmp() and setjmp() functions are not part of the C++ language, the header files included with the Microsoft C++ compiler do not allow the use of the longjmp() and signal() functions in a C++ program. These functions are needed to trap floating-point exceptions. This article explains why these functions are not defined, and how you can trap floating-point exceptions in C++.

MORE INFORMATION

Using longjmp() in C is potentially dangerous because if you dynamically allocate memory, then do a longjmp() before freeing the memory, that memory may end up never being freed.

The longjmp() and setjmp() functions are not part of the C++ language because in C++, longjmp() is potentially more dangerous. There is significantly more implicit dynamic memory allocation taking place in C++, with many new and delete operations occurring as objects are constructed and deleted. For this reason, longjmp() and setjmp() are not defined when compiling C++ programs. Both longjmp() and setjmp() are within a "#ifndef __cplusplus" section in SETJMP.H.

In C++, exceptions are normally handled by try catch blocks. You can use TRY and CATCH to catch some exceptions predefined in the Microsoft Foundation Classes (MFC), such as CFileException and CMemoryException; however, there are no exception classes for floating-point errors.

There is a technique similar to that used by the Microsoft Foundation Classes that you can use to trap floating-point exceptions using C++; that is, prototype longjmp() and setjmp() yourself. Also, to allow signal() to be called with either a handler that takes two parameters (_SIG_FPE) or just one parameter (all other signal values), signal() must be prototyped differently to accept a handler with a variable-length function list. The new prototype could be:

   void (__cdecl * __cdecl signal(int, void (__cdecl *)(int, ...)))(int);

In this case, whenever you call signal(), you must cast its second parameter with the following cast:

   (void (__cdecl *)(int, ...))

Appended below is SIGCPP.H, a header file that consists of the modified and combined header files SIGNAL.H and SETJMP.H. To use it,
#include <sigcpp.h>, and make sure that SIGNAL.H and SETJMP.H are not
included--and remember to use the above cast in signal() calls.

NOTE: This solution is not guaranteed to work in every case. If used with care, this solution will probably work; however, Microsoft does not recommend the use of longjmp() with C++. Using longjmp() with C++ may result in objects not being properly destroyed. If the objects that aren't destroyed allocate resources such as memory or file handles, these resources will not be deallocated.

Sample Code

/***
* SIGCPP.H - Header file that allows the use of signal() for the * handling of floating point and other exceptions in both C and C++. * However, it is recommended that longjmp() not be used in C++ programs. * - Do not #include <signal.h> or <setjmp.h>. * - Whenever you call signal(), you need to put the following cast on * its second parameter, your handler:
*       (void (__cdecl *)(int, ...))
* - Be very careful to avoid memory leakage with longjmp()'s in C++, * which will occur if destructors and other deletes are jumped. ****/

#ifndef _INC_SIGCPP

#ifdef __cplusplus extern "C" { #endif

#if (_MSC_VER <= 600)

#define __cdecl     _cdecl
#define __far       _far
#endif

////// Modified SIGNAL.H definitions:

#ifndef _SIG_ATOMIC_T_DEFINED typedef int sig_atomic_t;
#define _SIG_ATOMIC_T_DEFINED
#endif

#define NSIG 23     /* Maximum signal number + 1 */

/* signal types */

#ifndef _WINDOWS
#define SIGINT  2  /* CTRL+C sequence */
#define SIGILL  4  /* Illegal instruction - invalid function image */
#endif
#define SIGFPE  8  /* Floating-point exception */
#ifndef _WINDOWS
#define SIGSEGV 11 /* Segment violation */
#define SIGTERM 15 /* Software termination signal from kill */
#define SIGABRT 22 /* Abnormal termination triggered by abort call */
#endif

/* SIGNAL ACTION CODES */

/* Default signal action */
#define SIG_DFL (void (__cdecl *)(int))0

/* Ignore */
#define SIG_IGN (void (__cdecl *)(int))1

/* Signal error value (returned by signal call on error) */
#define SIG_ERR (void (__cdecl *)(int))-1

/* FUNCTION PROTOTYPES */

void (__cdecl * __cdecl signal(int,
     void (__cdecl *)(int, ...)))(int);
int __cdecl raise(int);

////// Modified SETJMP.H definitions:

/* Define the buffer type for holding the state information */

#define _JBLEN  9  /* bp, di, si, sp, ret addr, ds */

#ifndef _JMP_BUF_DEFINED typedef int jmp_buf[_JBLEN];
#define _JMP_BUF_DEFINED
#endif

/* Function prototypes */

int  __cdecl setjmp(jmp_buf);
void __cdecl longjmp(jmp_buf, int);

#ifdef __cplusplus } #endif /* __cplusplus */

#define _INC_SIGCPP
#endif /* _INC_SIGCPP */


Additional reference words: kbinf 1.00 1.50 7.00 8.00 8.00c
KBCategory: kbprg kbcode
KBSubcategory: CPPLngIss
Keywords : kb16bitonly
Technology : kbMfc


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: July 22, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.