Windows Exception Handling

Agenda :
what is exception ?
what causes an exception ?
what are the type of exception handler exist ?
who sees it first ?
What windows does by default ?
when you need to register handlers ?
What is windows exception (at OS level) ?
An exception is an event that stops the normal execution of code
It typically originates from one of two places :
Hardware (the CPU)
Software
Hardware (CPU) : The CPU tries to execute an instruction but cannot
Example : Access Violation , Integer Divide by Zero
int* ptr = nullptr; // Pointer is NULL (address 0) *ptr = 42; // CRASH! Writing to address 0 is illegalThe CPU executes the instruction to write 42 to address 0x0. The CPU hardware refuses and triggers an interrupt. The Windows Kernel catches this interrupt and converts it into an Exception Code (like 0xC0000005).
Software : Your program explicitly tells the OS to trigger an exception using the windows API function RaiseException().
The Exception Handling Hierarchy (Order of Precedence) :
When that exception occurs, Windows looks for a handler in a specific order. It does not go straight to your try/catch block immediately.
Order of Precedence :
Debugger (if attached) : If a debugger is attached , windows pauses execution and lets the debugger know --> this is called as the first chance exception
Vectored Exception Handler (VEH) : if no debugger handles it (or none is attached), windows pauses the execution and calls VEH
Priority : Highest priority within the application.
Scope : Global (Process-wide). It handles exceptions from any thread.
Registration : You must manually register this using AddVectoredExceptionHandler.
Structured Exception Handling :
Priority : Lower than VEH
Scope : Local (Thread based and stack based) , It looks for try , catch , except blocks in your specific function and then checks the function that called it , and so on (unwinding the stack)
UnHandledExceptionFilter : if no SEH handles it , the system calls a top level filter
Default system handler : if nothing else handles it , windows takes over .

Do we need to register the handlers (or) windows do this by default ? we need to register the handlers only if we want to prevent the application from getting crashed or log the error before dying. If we are okay with the program closing when it crashes, you do not need to write any handling code.
If you do not register any handlers (VEH or SEH) and your code crashes: 1. Windows invokes the Default Exception Handler. 2. This handler typically collects crash data (Windows Error Reporting). 3. It displays the "Application has stopped working" dialog or simply kills the process silently. 4. The application exits immediately. It does not recover.
Examples :
0x01 - The Default Behavior : No Handler
This program will just crash and close.
#include <iostream>
int main() {
int* badPtr = nullptr;
*badPtr = 10; // Exception triggered here by CPU
return 0;
}
0x02 - Structured Exception handler
This is the standard way to handle errors in specific blocks of code
#include <windows.h>
#include <iostream>
int main() {
__try {
// Protected code block
int* badPtr = nullptr;
*badPtr = 10;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
// Windows found this handler on the stack!
std::cout << "Caught an Access Violation! The program is saved." << std::endl;
}
std::cout << "Program continues execution..." << std::endl;
return 0;
}
0x03 - Vectored exception Handler
This handler is called before the SEH block above, even if the crash happens deep inside a function.
#include <windows.h>
#include <iostream>
// Your custom VEH function
LONG WINAPI MyVectoredHandler(PEXCEPTION_POINTERS pExceptionInfo) {
if (pExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
std::cout << "[VEH] I saw the crash FIRST (Global Handler)!" << std::endl;
// OPTIONAL: You can try to fix it, or tell Windows to keep searching.
// EXCEPTION_CONTINUE_SEARCH tells Windows to let SEH (the next handler) try.
return EXCEPTION_CONTINUE_SEARCH;
}
return EXCEPTION_CONTINUE_SEARCH;
}
int main() {
// Register the VEH
AddVectoredExceptionHandler(1, MyVectoredHandler);
__try {
int* badPtr = nullptr;
*badPtr = 10;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
std::cout << "[SEH] Caught locally." << std::endl;
}
return 0;
}
Output of the VEH example:
I saw the crash FIRST (Global Handler)! (VEH runs first) Caught locally. (Because VEH returned CONTINUE_SEARCH, SEH got a chance).
Want to dive deeper into Windows internals?
Check out my other blog posts for more deep dives!