Microsoft KB Archive/106261

From BetaArchive Wiki
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

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 <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 query words: kbinf 1.00 1.50 7.00 8.00 8.00c

Keywords : kb16bitonly
Issue type :
Technology : kbVCsearch kbAudDeveloper kbPTProdChange kbvc150 kbvc100 kbZNotKeyword3 kbCVC700DOS


Last Reviewed: May 9, 2001
© 2001 Microsoft Corporation. All rights reserved. Terms of Use.