Chapter 25 -- Unhandled Exceptions and C Exceptions

[Previous] [Next]

Chapter 25

In the previous chapter, we discussed what happens when a filter returns EXCEPTION_CONTINUE_SEARCH. Returning this tells the system to continue walking up the call tree looking for additional exception filters. But what happens if every filter returns EXCEPTION_CONTINUE_SEARCH? In this case, we have what's called an unhandled exception.

Remember from Chapter 6 that every thread truly begins executing with a function inside Kernel32.dll called BaseProcessStart or BaseThreadStart. These two functions are practically identical; the only difference is that one function is used for a process's primary thread:

 VOID BaseProcessStart(PPROCESS_START_ROUTINE pfnStartAddr) { _ _try { ExitThread((pfnStartAddr)()); } _ _except (UnhandledExceptionFilter(GetExceptionInformation())) { ExitProcess(GetExceptionCode()); } // NOTE: We never get here } 

The other function is used for all of a process's secondary threads:

 VOID BaseThreadStart(PTHREAD_START_ROUTINE pfnStartAddr, PVOID pvParam) { _ _try { ExitThread((pfnStartAddr)(pvParam)); } _ _except (UnhandledExceptionFilter(GetExceptionInformation())) { ExitProcess(GetExceptionCode()); } // NOTE: We never get here } 

Notice that both of these functions contain an SEH frame. Both functions enter a try block and from within the try block call your primary or secondary thread's entry-point function. So, if your thread raises an exception and if all your filters return EXCEPTION_CONTINUE_SEARCH, the system has provided a special filter function that will be called for you automatically: UnhandledExceptionFilter.

 LONG UnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo); 

This function is responsible for displaying the message box that indicates that a thread in your process has an unhandled exception and allows the user to terminate or debug the process. This message box looks similar to the following in Windows 98.

In Windows 2000, it looks like this.

click to view at full size.

In the Windows 2000 message box, the first paragraph of text indicates which exception occurred and the address of the instruction in the process's address space that generated the exception. It just so happens that a memory access violation caused this message box to appear, so the system can report the invalid memory address that was accessed and specify that an attempt to read the memory caused the exception. The UnhandledExceptionFilter function gets this additional information from the ExceptionInformation member of the EXCEPTION_RECORD structure generated for this exception.

Following the description of the exception, the message box indicates the user's two choices. The first choice is to click on the OK button, which causes UnhandledExceptionFilter to return EXCEPTION_EXECUTE_HANDLER. This, of course, causes a global unwind to occur so that any finally blocks that you have are executed, and then the handler in BaseProcessStart or BaseThreadStart executes. Both of these handlers call ExitProcess, which is why your process terminates. Note that the process's exit code will be the exception code. Also note that it is your process's thread that is killing your process—the operating system is not doing it! This means that you have control over this behavior and can alter it.

The second choice, clicking on the Cancel button, is a developer's dream come true. When you click on the Cancel button, UnhandledExceptionFilter attempts to load a debugger and attaches the debugger to the process. With the debugger attached to the process, you can examine the state of global, local, and static variables, set breakpoints, examine the call tree, restart the process, and do anything else you would normally do when you debug a process.

The real boon is that you can handle the failure of your application when it occurs. Under most other operating systems, you must invoke your application through the debugger to debug it. If an exception occurs in a process on one of these other operating systems, you have to terminate the process, start a debugger, and invoke the application—again using the debugger. The problem is that you would have to try to reproduce the bug before you could fix it. And who knows what the values of the different variables were when the problem originally occurred? It's much harder to resolve a bug this way. The ability to dynamically attach a debugger to a process as it runs is one of the best features in Windows.

Windows 2000

This book concentrates solely on user-mode application development. However, you might find it interesting to know what happens when a thread running in kernel-mode raises an unhandled exception. Exceptions in kernel mode are handled exactly the same as exceptions in user mode. If a low-level virtual memory function generates an exception, the system checks whether any kernel-mode exception filters are prepared to handle the exception. If the system cannot find an exception filter to handle the exception, the exception is unhandled. In the case of a kernel-mode exception, the unhandled exception is in the operating system or (more likely) in a device driver and not in an application. Such an unhandled exception identifies a serious bug!

It isn't safe for the system to continue running if an unhandled exception occurs in kernel mode, so the system doesn't call the UnhandledExceptionFilter function in such a case; instead, the system shows what is typically called the Blue Screen of Death. The display switches video mode to a blue screen containing nothing but text and the computer is halted. The text displays which device drivers are loaded and the module containing the code that raised the unhandled violation. You should jot down this information and send it to Microsoft or to the device driver vendor so that the bug can be fixed. Since the computer is halted, you'll need to reboot your machine before you can do anything else; any unsaved work is lost.



Programming Applications for Microsoft Windows
Programming Applications for Microsoft Windows (Microsoft Programming Series)
ISBN: 1572319968
EAN: 2147483647
Year: 1999
Pages: 193

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net