260 likes | 489 Views
Structured Exception Handling. OVERVIEW. Structured Exception Handling (SEH) provides a robust mechanism for applications to respond to unexpected events Hardware faults Addressing exceptions System errors User generated exceptions SEH assures the ability to free resources Perform clean-up
E N D
OVERVIEW • Structured Exception Handling (SEH) provides a robust mechanism for applications to respond to unexpected events • Hardware faults • Addressing exceptions • System errors • User generated exceptions • SEH assures the ability to free resources • Perform clean-up • SEH simplifies program logic
PARTS • Part I Exception Handlers • Part II Termination Handlers
PART I Exception Handlers
TRY AND EXCEPT BLOCKS • __try and __except • Keywords recognized by Visual C++ compiler • Actual keywords are specific to the compiler • __try { • /* Block of monitored code */ • } • __except (filter_expression) { • /* Exception handling block */ • }
SEH, BLOCKS, AND FUNCTIONS { DWORD x1; /* Block 1 */ ... _try { /* Block 2 */ DWORD x2; .... x2 = f (x1); .... } _except () { /* SEH 2 */ } } DWORD f (DWORD y) { /* Block f */ DWORD z; z = y / (y - 1); return z / y; } STACK Windows Exception Handler Block 1 x1 Block 2 x2 SEH 2 Block f y z Exception Occurs Execute this SEH
FILTER EXPRESSIONS • The filter_expression is evaluated after an exception • It is a literal constant, expression, or a function call • Returns one of three values • EXCEPTION_EXECUTE_HANDLER • Normal case • EXCEPTION_CONTINUE_SEARCH • This handler does not process this exception; unwind the stack for the next exception handler • EXCEPTION_CONTINUE_EXECUTION • Some exceptions cannot be continued, and another exception would occur immediately
EXCEPTION CODES (1 of 2) • How do you know what exception occurred? • And how do you know what filter expression value to generate? • DWORD GetExceptionCode (VOID) • The filter function itself cannot call GetExceptionCode, so a common usage is: • __except (MyFilter (GetExceptionCode ())) { . . . • }
EXCEPTION CODES (2 of 2) • An alternative function that returns additional information: • LPEXCEPTION_POINTERS • GetExceptionInformation (VOID) • including information on the virtual address causing an access violation
EXCEPTION CODE VALUES (1 of 2) • 1. Program violations, including: • EXCEPTION_ACCESS_VIOLATION • EXCEPTION_DATATYPE_MISALIGNMENT • EXCEPTION_NONCONTINUABLE_EXECUTION • 2.. Memory allocation exceptions (See Chapter 4) • (HeapAlloc and HeapCreate) • STATUS_NO_MEMORY
EXCEPTION CODE VALUES (2 of 2) • 3. User-defined exception codes • 4. Arithmetic codes, such as: • EXCEPTION_INT_DIVIDE_BY_ZERO • EXCEPTION_FLT_DIVIDE_BY_ZERO • 5. Debugger exceptions — EXCEPTION_BREAKPOINT
EXCEPTION CONTROL FLOW _try { . . . i = j / 0; . . . } _except (Filter (GetExceptionCode ())) { . . . } . . . DWORD Filter (DWORD ExCode) { switch (ExCode) { . . . case EXCEPTION_INT_DIVIDE_BY_ZERO: . . . return EXCEPTION_EXECUTE_HANDLER; case . . . } } 1 2 6 7 3 4 5
USER-GENERATED EXCEPTIONS(1 of 2) • VOID RaiseException (DWORD dwExceptionCode, • DWORD dwExceptionFlags, DWORD cArguments, • LPDWORD lpArguments) • dwExceptionCode bits 31, 30: • 0 — Success 1 — Informational • 2 — Warning 3 — Error • Bit 29: Set • Bit 28: 0 Bits 27–0: User Specified • Typical value: 0XE0000006
USER-GENERATED EXCEPTIONS(2 of 2) • dwExceptionFlags — EXCEPTION_NONCONTINUABLEindicates filter expression should not generate • EXCEPTION_CONTINUE_EXECUTION • lpArguments — If not NULL, points to an array of cArguments • EXCEPTION_MAXIMUM_PARAMETERS == 15
ReportException Function (1 of 2) • VOID ReportException (LPCTSTR UserMessage, • DWORD ExceptionCode) • /* ReportException */ • /* Extension of ReportError to generate a user • exception code rather than terminating. */ • /* UserMessage: Message to be displayed • ExceptionCode: 0 - Return • > 0 - ExitProcess with this code */ • { • /* Report as a non-fatal error */ • if (lstrlen (UserMessage) > 0) • ReportError (UserMessage, 0, TRUE);
ReportException Function (2 of 2) • /* If fatal, raise an exception */ • /* Mask out any high order bits in the */ • /* user-supplied exception code */ • if (ExceptionCode != 0) • RaiseException ( • (0x0FFFFFFF & ExceptionCode) | • 0xE0000000, 0, 0, NULL); • return; • }
ENABLING FLOATING POINT EXCEPTIONS (1 of 2) • Skip if you are not interested in floating point arithmetic • To enable floating point exceptions, you need to set the fp mask (set the bit off to enable the exception) • int iFPMask; /* Save old control mask */ • iFPMask = _controlfp (0, 0); • iFPMask &= ~(EM_OVERFLOW | EM_UNDERFLOW | • EM_INEXACT | EM_ZERODIVIDE | EM_DENORMAL); • _controlfp (iFPMask, MCW_EM); • /* Set new control mask*/ • /* Restore the old mask to disable exceptions */ • _controlfp (iFPMask, 0xFFFFFFFF);
ENABLING FLOATING POINT EXCEPTIONS (2 of 2) • Formula: (current_mask & ~mask) | (new & mask) • After a FP exception, clear it with _clearfp()
PART II Termination Handlers
TRY-FINALLY BLOCKS • Example: The finally block (almost) always exectutes • while (...) __try { • hTemp = CreateFile (TempFileName, ...); • /* Block of guarded code */ • ... • if (...) break; /* finally block will run */ • ... • } • __finally { /* Executes on every loop iteration */ • /* termination handler (finally block) */ • CloseHandle (hTemp); • DeleteFile (TempFileName); • }
TERMINATION HANDLERS • Executed whenever control flow leaves the try block because of: • Reaching the end of the __try block • Leaving the block because of execution of: returnbreak longjump continuegoto __leave • An exception • Executed in the context of the block or function it guards • Control can pass from end of termination handler to next statement
ABNORMAL TERMINATION • To detect termination for any reason other than reaching the end of the try block—use • BOOL AbnormalTermination (VOID) • to determine how the try block terminated • TRUE — For abnormal termination • FALSE — For normal termination
COMBINING FINALLY ANDEXCEPT BLOCKS (1 of 2) • __try { • /* Block of guarded code */ • } • __except (filter_expression) { • /* Except block */ • } • __finally { • /* You cannot do this ! */ • }
COMBINING FINALLY ANDEXCEPT BLOCKS (2 of 2) • __try { /* Outer try-except block */ • while (...) __try { /* Inner try-fin block */ • hFile = CreateFile (TempFile, ...); • if (...) __try { /* Inner try-ex block */ • ... • } • __except (EXCEPTION_EXECUTE_HANDLER) { • ... /* Process FP exception. */ _clearfp(); • } • } • __finally { /* End of while loop */ • CloseHandle (hFile); DeleteFile (TempFile); • } • } • __except (filter-expression) { }