Exception Handling in Windows

CSK 1 Reputation point
2024-10-25T07:40:37.14+00:00

Windows provides the following exception handling frameworks:

  1. Structured Exception Handling (SEH)
  2. Vectored Exception Handling (VEH)

SEH is just the Windows's version of the C++ try-catch, and documentation suggests using the C++ try-catch blocks. I don't want to use try-catch everywhere but have a single 'catch-all' exception handler.

That leads to VEH, which, unlike SEH is not a frame-based exception handling construct (frame-based exception handling is defined here). VEH is for the entire process and not just each thread. This post describes VEH contrasted with SEH.

But there is one more technique - UnHandledExceptionFilter. This is actually part of SEH. In Windows, the __except part contains a filter expression (described in detail here), which decides whether to invoke the exception handler (which follows the __except clause or pass it to other exception handlers in the stack).

__try {
    // guarded code
}
__except ( /* filter expression */ ) {
    // the exception handler (as Windows calls it)
}

Now, if none of the exception handlers are matched, then the exception handler set using the SetUnhandledExceptionFilter method is invoked. To me, it looks like a non-frame-based exception handler (like VEH), but this is also the last handler which catches all exceptions that weren't caught by the SEH's __except clause, which is frame-based. In my case, if I don't write any try-except blocks, the method I set using SetUnhandledExceptionFilter gets invoked - which makes sense because there were 0 exception handlers, so by default, all exceptions are considered 'unfiltered' and trigger the UnhandledExceptionFilter.

Now, I'm not sure which one to use - VEH or UnhandledExceptionFilter. VEH is not frame-based and gets invoked before all frame-based exception handlers (SEH) and UnhandledExceptionFilter. Both can handle all 'uncaught exceptions'.

Next, after catching an exception (using VEH or UnhandledExceptionFilter) on a worker thread (threads created by app), what is the expectation? Can the app continue?

Here's a sample scenario: If there was a division by zero or access violation due to a bug on a worker thread, I'd like to signal the main thread and kill the worker thread. The main thread finalizes all my structures, shows a message box to user with two options - Restart & Quit, and if user chooses to Restart, initialize all my structures again. This is possible but is this recommended?

Regarding return values, VEH documentation says:

To return control to the point at which the exception occurred, return EXCEPTION_CONTINUE_EXECUTION (0xffffffff). To continue the handler search, return EXCEPTION_CONTINUE_SEARCH (0x0).

and UnhandledExceptionFilter documentation says there are the following return values - EXCEPTION_CONTINUE_SEARCH and EXCEPTION_EXECUTE_HANDLER, different from VEH.

What if an exception occurs in the main thread? Then, the VEH and UnhandledExceptionFilter gets invoked on main thread. I can't kill the thread in that scenario. What is Window's recommendation?

There's also this other stackoverflow post which says VEH doesn't replace UnhandledExceptionFilter and should be used as a diagnostic tool only, but I didn't understand.

Basically, I want to know Windows's recommended way to cleanly handle exceptions in a Windows app. Summarizing my questions as follows:

  1. VEH vs UnhandledExceptionFilter - which one to use and why? What is Windows's recommendation?
  2. After catching an exception (in both cases - main thread or worker thread), how should the app behave?

Note: I'm aware that killing a thread is not a good practice and has some consequences (one being, the stack doesn't unwind), but that's not the main focus of this post. If I kill the thread, I don't have to deal with recursive exceptions and I can potentially restart the app in the same process space.

Update1: I cannot use try-catch for few reasons - it works only if you throw an exception (I might be wrong here)... It doesn't catch division by zero (as shown here). I'm not hands-on with it, but it's a guideline in my project to never use try-catch, unless a third-party API which throws, is used. All funcs are marked noexcept. There are other reasons, but that'd digress from this post.

Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,666 questions
{count} votes

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.