PRODUCT : Borland C++ NUMBER : 1715 VERSION : 3.X OS : WIN DATE : October 25, 1993 PAGE : 1/9 TITLE : How to Catch Floating Point Exceptions The default exception handler in the Borland run-time library exits the program. Usually this is too drastic, but using signal() you can catch when these exceptions occur and recover from them. The important thing to remember about signal() is that your exception catcher routine must call signal again if you want to continue catching exceptions. If you don't, you'll get the first exception and if another exception were to occur, the default handler will terminate your application. There are some exceptions that are handled by Windows before the run-time library has a chance to catch it. These are called critical errors. If Windows detect a critical error, it will display a system modal dialog box (the kind you get with the dreaded UAE or GPF). If you don't want the dialog to show up at all, you can call SetErrorMode() to disable this feature of Windows. The following is a sample program on how you can trap floating point exceptions. The sample program divides by zero is two different places: in a dll and in an exe and the exception handler catches them and continues on as if nothing happened. # # makefile # .autodepend ROOT = CatchFlt OBJ = $(ROOT).obj LIB = test.lib INCLUDE = e:\bc31\include CC = bcc -H=$(ROOT).pch -ml -WS -w -v -D_CLASSDLL .c.obj: $(CC) -c {$< } .cpp.obj: $(CC) -c {$< } $(ROOT).exe: $(ROOT).def $(OBJ) $(LIB) tlink /m /s /c /C /v @&&! c0wl $(OBJ) PRODUCT : Borland C++ NUMBER : 1715 VERSION : 3.X OS : WIN DATE : October 25, 1993 PAGE : 2/9 TITLE : How to Catch Floating Point Exceptions $(ROOT).exe import.lib $(LIB) mathwl.lib crtldll.lib $(ROOT).def ! rc $(ROOT).res $(ROOT).exe buildsym $(ROOT).exe $(ROOT).obj: $(ROOT).cpp $(LIB): test.c bcc -WD test.c implib test.lib test.dll // ******************************************************** // // Filename: test.c // // // // Date: Oct 10, 1993 // // ******************************************************** // #include float _export testfloat(float a) { double b=0.0; double t = a/b; return (float)(t); } #pragma argsused int FAR PASCAL LibMain(HANDLE a, WORD b, WORD c, LPSTR d) { return 1; } #pragma argsused int PASCAL WEP(int a) { return 1; } PRODUCT : Borland C++ NUMBER : 1715 VERSION : 3.X OS : WIN DATE : October 25, 1993 PAGE : 3/9 TITLE : How to Catch Floating Point Exceptions ; test.def LIBRARY test description 'test dll' code preload moveable // ******************************************************** // // Filename: catchflt.h // // // // Date: Oct 10, 1993 // // ******************************************************** // #ifndef CatchFlt_H #define CatchFlt_H 1 #define lpszAPPSTR "CatchFlt" #define lpszMENUNAME NULL #define lpszCLASSNAME "CatchFltClass" #define lpszTITLE "CatchFlt Window" int PASCAL WinMain(HINSTANCE, HINSTANCE, LPSTR, int); BOOL InitApplication(HINSTANCE); BOOL InitInstance(HINSTANCE, int); LRESULT FAR PASCAL _export MainWndProc(HWND, UINT, WPARAM, LPARAM); void InitSignal(void); void Catcher(int, int); #endif // ******************************************************* // // Filename: catchflt.cpp // // // // Date: Oct 10, 1993 // // ******************************************************* // #define WIN31 #define STRICT #include #include #include #include #include PRODUCT : Borland C++ NUMBER : 1715 VERSION : 3.X OS : WIN DATE : October 25, 1993 PAGE : 4/9 TITLE : How to Catch Floating Point Exceptions #pragma hdrstop #include "CatchFlt.h" // Save the program's instance handle HINSTANCE hInst; extern "C" float testfloat(float a); // -------------------------------------------------------- // // Starting point of all Windows programs // // -------------------------------------------------------- // #pragma argsused int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { MSG msg; if (!hPrevInstance) // Any previous instance? if (!InitApplication(hInstance)) // Initialize app- specific stuff return FALSE; if (!InitInstance(hInstance, nCmdShow)) // Instance-specific return FALSE; // Standard Windows message loop while (GetMessage(&msg, NULL, NULL, NULL)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (msg.wParam); } // --------------------------------------------------------------- // // Initialize application-specific stuff and register the class // // --------------------------------------------------------------- // BOOL InitApplication(HINSTANCE hInstance) { PRODUCT : Borland C++ NUMBER : 1715 VERSION : 3.X OS : WIN DATE : October 25, 1993 PAGE : 5/9 TITLE : How to Catch Floating Point Exceptions WNDCLASS wc; wc.style = NULL; wc.lpfnWndProc = (WNDPROC) MainWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszMenuName = lpszMENUNAME; wc.lpszClassName = lpszCLASSNAME; return (RegisterClass(&wc)); } // --------------------------------------------------------------- // // Initialize instance and display the main window // // --------------------------------------------------------------- // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; hInst = hInstance; hWnd = CreateWindow(lpszCLASSNAME, lpszTITLE, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); if (!hWnd) return FALSE; ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); PRODUCT : Borland C++ NUMBER : 1715 VERSION : 3.X OS : WIN DATE : October 25, 1993 PAGE : 6/9 TITLE : How to Catch Floating Point Exceptions return TRUE; } // --------------------------------------------------------------- // // InitSignal // // Set signal handler to be our own catcher // // --------------------------------------------------------------- // void InitSignal(void) { if (signal(SIGFPE, (void (*)(int))Catcher) == SIG_ERR) { MessageBox(NULL, "Error installing signal handler", "Error", MB_OK | MB_ICONSTOP); PostQuitMessage(0); } } // --------------------------------------------------------------- // // Floating point exception handler // // NOTE: it is important to reset our handler after we get // // called. Otherwise, our handler won't get called // // again. // // --------------------------------------------------------------- // void Catcher(int ExceptionType, int ExceptionError) { char buf[20]; // make sure it is a floating point exception if (ExceptionType == SIGFPE) PRODUCT : Borland C++ NUMBER : 1715 VERSION : 3.X OS : WIN DATE : October 25, 1993 PAGE : 7/9 TITLE : How to Catch Floating Point Exceptions { switch (ExceptionError) { case FPE_ZERODIVIDE: InitSignal(); MessageBox(GetFocus(), "You divided by zero!!!", "Catcher", MB_OK); break; default: wsprintf(buf, "unknown exception %d\n\r", ExceptionType); MessageBox(GetFocus(), buf, "Catcher", MB_OK | MB_ICONSTOP); break; } } } // --------------------------------------------------------------- // // WM_DESTROY // // --------------------------------------------------------------- // #pragma argsused void Main_OnDestroy(HWND hwndMain) { PostQuitMessage(0L); } // --------------------------------------------------------------- // // WM_CREATE // // --------------------------------------------------------------- // #pragma argsused BOOL Main_OnCreate(HWND hwndMain, CREATESTRUCT *lpcs) { PRODUCT : Borland C++ NUMBER : 1715 VERSION : 3.X OS : WIN DATE : October 25, 1993 PAGE : 8/9 TITLE : How to Catch Floating Point Exceptions InitSignal(); return TRUE; } // --------------------------------------------------------------- // // WM_LBUTTONDOWN // // --------------------------------------------------------------- // #pragma argsused void Main_OnLButtonDown(HWND hwndMain, BOOL fDoubleClick, int x, int y, UINT keyFlags) { double d1, d2=0.0, t; d1 = 3.14159265354; d1 = d1/2.0; t = testfloat(d1); // cause exception here! t = d1/d2; // and here! } // --------------------------------------------------------------- // // Standard message-handler routine for main window // // --------------------------------------------------------------- // LRESULT FAR PASCAL _export MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { HANDLE_MSG(hWnd, WM_CREATE, Main_OnCreate); HANDLE_MSG(hWnd, WM_DESTROY, Main_OnDestroy); HANDLE_MSG(hWnd, WM_LBUTTONDOWN, Main_OnLButtonDown); } // default behaviour return (DefWindowProc(hWnd, message, wParam, lParam)); PRODUCT : Borland C++ NUMBER : 1715 VERSION : 3.X OS : WIN DATE : October 25, 1993 PAGE : 9/9 TITLE : How to Catch Floating Point Exceptions } ; catchflt.def NAME CatchFlt EXETYPE WINDOWS DESCRIPTION 'Catching Float-Exceptions Application' CODE PRELOAD MOVEABLE DISCARDABLE DATA PRELOAD MOVEABLE MULTIPLE HEAPSIZE 1024 STACKSIZE 8192 DISCLAIMER: You have the right to use this technical information subject to the terms of the No-Nonsense License Statement that you received with the Borland product to which this information pertains.