Microsoft KB Archive/106261

{|
 * width="100%"|

How to Trap Floating-Point Exceptions Using C++

 * }

Q106261

-

The information in this article applies to:


 * Microsoft C/C++ for MS-DOS, version 7.0
 * Microsoft Visual C++, versions 1.0, 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 , 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  or .
 * - 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.


 * 1) ifndef _INC_SIGCPP

extern "C" {
 * 1) ifdef __cplusplus
 * 1) endif


 * 1) if (_MSC_VER <= 600)
 * 2) define __cdecl    _cdecl
 * 3) define __far      _far
 * 4) endif

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

typedef int sig_atomic_t;
 * 1) ifndef _SIG_ATOMIC_T_DEFINED
 * 1) define _SIG_ATOMIC_T_DEFINED
 * 2) endif


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

/* signal types */


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

/* SIGNAL ACTION CODES */

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

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

/* Signal error value (returned by signal call on error) */
 * 1) 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 */


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

typedef int  jmp_buf[_JBLEN];
 * 1) ifndef _JMP_BUF_DEFINED
 * 1) define _JMP_BUF_DEFINED
 * 2) endif

/* Function prototypes */

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

}
 * 1) ifdef __cplusplus
 * 1) endif /* __cplusplus */

Additional query words: kbinf 1.00 1.50 7.00 8.00 8.00c
 * 1) define _INC_SIGCPP
 * 2) endif /* _INC_SIGCPP */

Keywords : kb16bitonly

Issue type :

Technology : kbVCsearch kbAudDeveloper kbPTProdChange kbvc150 kbvc100 kbZNotKeyword3 kbCVC700DOS