Microsoft KB Archive/106261: Difference between revisions
m (Text replacement - "<" to "<") |
m (Text replacement - ">" to ">") |
||
Line 42: | Line 42: | ||
<pre class="CODESAMP"> (void (__cdecl *)(int, ...)) </pre> | <pre class="CODESAMP"> (void (__cdecl *)(int, ...)) </pre> | ||
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 | 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.<br /> | ||
<br /> | <br /> | ||
'''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. | '''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. | ||
Line 52: | Line 52: | ||
* handling of floating point and other exceptions in both C and C++. | * handling of floating point and other exceptions in both C and C++. | ||
* However, it is recommended that longjmp() not be used in C++ programs. | * However, it is recommended that longjmp() not be used in C++ programs. | ||
* - Do not #include <signal.h | * - Do not #include <signal.h> or <setjmp.h>. | ||
* - Whenever you call signal(), you need to put the following cast on | * - Whenever you call signal(), you need to put the following cast on | ||
* its second parameter, your handler: | * its second parameter, your handler: |
Latest revision as of 17:44, 20 July 2020
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 |