How to Trap Floating-Point Exceptions Using C++ID: Q106261
|
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++.
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.
/***
* 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 query words: kbinf 1.00 1.50 7.00 8.00 8.00c
Keywords : kb16bitonly
Version :
Platform :
Issue type :
Last Reviewed: July 28, 1999