Login | Register   
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


advertisement
 

Dealing with Floating-point Exceptions in MSVC7\8 : Page 3

Learn how to catch floating-point exceptions in C\C++ code.


advertisement
Catching the Floating-point Exceptions
The try-except statement is a Microsoft extension to the C and C++ languages that enables 32-bit target applications to gain control when exceptions occur. These exceptions call C, or structured or Win32 exceptions and are identified by an unsigned integer value. Also, they are referenced as "asynchronous." This means that they are secondary to the normal flow of control. According to Intel documentation, in the native mode (not MS DOS), the software exception handler is invoked immediately before the execution of the next floating-point instruction—unless it is not one of the non-waiting instructions, the WAIT\FWAIT instruction, or the next MMX™ instruction. The following code snippet shows how to use C exception handling mechanism:

__try //The start of the guarded block. { //Code that may generate a floating-point exception } //The end of the guarded block. __except (EvaluateException(GetExceptionCode())) { //May evaluate globalVar here //Code that does appropriate processing } //May evaluate globalVar here

When an exception occurs during the execution of the guarded block or any function called from it, the _except expression is evaluated. Here, GetExceptionCode() retrieves the code that identifies the type of occurred exception. The EvaluateException() calls the filter expression and can be any function that returns an integer value. There are three predefined values that can be returned and that define the program execution pass. The values are defined in the excpt.h file, and they are:
  • EXCEPTION_EXECUTE_HANDLER: The except block is executed.
  • EXCEPTION_CONTINUE_SEARCH: The exception handler search continues.


  • EXCEPTION_CONTINUE_EXECUTION: Execution continues as the exception never occurred.
The following code shows an example of the filter expression for x86:

int EvaluateException(int exceptionCode) { //May evaluate exeptionCode //May set a global variable that can be evaluated in //or after _except guard code. globalVar = _clear87(); //Get floating-point status word. //The above function also sets the //busy bit to 0 to show that FPU //is not busy. return EXCEPTION_EXECUTE_HANDLER;//force execution of //the _except() guard code. }

Instead of calling EvaluateException(), you may call _fpieee_flt(). This function is defined in the fpieee.h file:

_fpieee_flt(GetExceptionCode(), GetExceptionInformation(), MyFpieeeHandler) You supply MyFpieeeHandler() according to its signature: int MyFpieeeHandler( _FPIEEE_RECORD* );

The possible return values are the same as for EvaluateException().

The following code shows an example of the filter expression for x86:

int EvaluateException(int exceptionCode) { unsigned long cntrReg = 0; _asm { stmxcsr [cntrReg] //Get MXCSR register and [cntrReg], 000000001h //Get invalid operation //flag bit 0. //bit 2 – divide-by-zero flag //bit 3 - overflow flag //bit 4 – underflow flag } if (cntReg > 0) { _asm { stmxcsr [cntrReg] //Get MXCSR register and [cntrReg], 0FFFFFFFEh //Clear sticky //invalid operation flag ldmxcsr [cntrReg] //Load MXCSR register } globalVar = _SW_INVALID; } return EXCEPTION_EXECUTE_HANDLER;//force execution of //the _except() guard code. }

If a C exception is raised in a C++ program, it can be handled as described above. However, for C++, Microsoft recommends that you use the C++ try-catch exception handling mechanism. This mechanism is fully "synchronous," meaning that it only occurs when it is thrown. The difference between C structured and C++ typed exception handling is that the latter requires the use of the ellipsis handler in order to catch the floating-point exceptions in C++ code. The following code demonstrates this:

try { //Code that may generate a floating-point exception } catch(. . .) { int fpStatusWord = _clear87(); //You may analyze the bits of the status word. //Code that does appropriate processing }

Author's Note: Use catch(. . .) with precaution; see the compilers option /EH below.

It's also possible to associate the Win32 exceptions with specific wrapper classes, as shown below. Here's how to define a wrapper:

class SeWrapper { private: unsigned int seCode; SeWrapper() {} public: SeWrapper(unsigned int n) : (seCode(n) {} ~SeWrapper() {} unsigned int GetSeCode() {return seCode;} };

Define a native compiled function (compiled with /c) according to the following signature:

void SeTranslator(unsigned int n, struct _EXCEPTION_POINTER* ptr) { //This function should throw an exception of SeWrapper class. throw SeWrapper(n); }

Install the translator function that will be called by the internal exception-handling mechanism when a C exception is thrown:

_set_se_translator(SeTranslator);

Each thread should install its own translator function. Now, you can use C++ typed exception:

try { //Code that may generate a floating-point exception } catch(SeWrapper ex) { //You may analyze ex. //Code that does appropriate processing }

After you have your code in place, you need to select right project properties.



Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap