Win32 Programming
Download
Report
Transcript Win32 Programming
Win32 Programming
Lesson 24: More SEH
That’s right… you’ll never generate an exception, will you?
Where are we?
Looked at __finally blocks…
But you can also deal with the exception
using __except
Basic structure
__try {
//code
} __except {
//exception handler
}
Note: you can’t have __except and __finally
in the same __try block
Example
DWORD Funcmeister1() {
DWORD dwTemp;
// 1. Do any processing here.
_ try {
// 2. Perform some operation.
dwTemp = 0;
} except (EXCEPTION_EXECUTE_HANDLER) {
// Handle an exception; this never executes.
}
// 3. Continue processing.
return(dwTemp);
}
Better Example
DWORD Funcmeister2() {
DWORD dwTemp = 0;
// 1. Do any processing here.
__try {
// 2. Perform some operation(s).
dwTemp = 5 / dwTemp;
// Generates an exception
dwTemp += 10;
// Never executes
} __except (EXCEPTION_EXECUTE_HANDLER) {
// 4. Handle an exception.
MessageBeep(0);
}
// 5. Continue processing.
return(dwTemp);
}
Example
See what was new?
__except (*) where * ==
EXCEPTION_EXECUTE_HANDLER
EXCEPTION_CONTINUE_SEARCH
EXCEPTION_CONTINUE_EXECUTION
EXCEPTION_EXECUTE_HANDLER
Execute the __except block and continue after it
Very useful for getting yourself out of trouble…
char* RobustStrCpy(
char* strDestination,
const char* strSource
) {
__try {
strcpy(strDestination, strSource);
} __except (EXCEPTION_EXECUTE_HANDLER) {
// Nothing to do here
}
return(strDestination);
}
Never causes the program to exit
However, does cause a global unwind…
Global Unwind?
Essentially, the computer has to unwind _try
blocks (because the __finally clauses have to
be executed) until it gets to the handling
__except block
That’s expensive in terms of CPU cycles
Odd Errors
Of course,
EXCEPTION_CONTINUE_EXECUTION can
cause strange errors
Imagine:
*buf = ‘R’
Assembles as: mov eax, [buf];
mov [eax], ‘R’
When we continue after fixing the error, what happens
depends on the target CPU and the compiler optimizations
BE WARNED!
EXECUTE_CONTINUE_SEARCH
Go up to the previous __except block and use
that exception handler…
But doesn’t call __finally blocks
This can make code hard to follow (remember
our example from last week?)
And Another…
Deciding what to do
As we saw in the previous example, we can
decide what to do in the __except () block
with a function
Sometimes we want to know what type of
exception occurred
Done with DWORD GetExceptionCode
Values defined in winbase.h
So…
_ _try {
x = 0;
y = 4 / x;
} _
_except ((GetExceptionCode() ==
EXCEPTION_INT_DIVIDE_BY_ZERO) ?
EXCEPTION_EXECUTE_HANDLER :
EXCEPTION_CONTINUE_SEARCH)
{
// Handle divide by zero.
}
Under The Hood
When an exception occurs, the OS pushes
three structures to the calling thread’s stack
EXCEPTION_RECORD
CONTEXT
EXCEPTION_POINTERS
Can access via
PEXECEPTION_POINTERS
GetExceptionInformation()
Finally…
(Or do I mean __finally?)
Remind me what happens inside the kernel
when we start a process?
ThreadStart/ProcStart
The primary thread (and subsequent threads)
are wrapped in a __try __except block
It’s this block which ultimately cancels the
process/thread
I’m sure you’ve all seen the box
Now you know where it comes from!
Assignment
No assignment today…
Lucky ewe…