How to register a vectored exception handler

2 05 2013

Recently just after we deployed our project in a Client machine, they reported a sporadic crash issue in their machine. :(. After analyzing the dump file, our Architect team found out that its happening from a particular COM Component. Unfortunately I was responsible for that component. 😦 😦

I tried to reproduce same issue in my development machine and was able to reproduce only in release configuratiin mode. Actually I have only the source code of my component in my machine.
So I was thinking about, how to find out this crash location in my source code. Yes, you are right some loggin mechanism. 🙂 Plus some exception handling mechanism too. 🙂 🙂

In case of exception occouered in our code, the operating system try to find out a handler which tells how to proceed now. If it fails, then we will get error message that our application is going to close!!!
In order to find such exception handler, the system has a fixed order to search.
It will start with the vectored exception handlers. So we can set a Vectored exception handler for our application using Windows API AddVectoredExceptionHandler.It registers a vectored exception handler.
The parameter of exception handler is pointer to a structure EXCEPTION_POINTERS. From this structure we get exception code and address where the exception occurred. Then using the method SymGetSymFromAddr64 from Dbghelp.dll, we can locate the symbol(function name) for that address.

char *Symbol(DWORD dwAddr)
    typedef struct _IMAGEHLP_SYMBOL64_L {
        DWORD   SizeOfStruct;
        DWORD64 Address;
        DWORD   Size;
        DWORD   Flags;
        DWORD   MaxNameLength;
        CHAR    Name[1];

    typedef BOOL (__stdcall *pfnSymInitialize) (HANDLE hProcess,
        PCSTR UserSearchPath, BOOL fInvadeProcess);
    typedef BOOL (__stdcall *pfnSymGetSymFromAddr64) (HANDLE hProcess,
        DWORD64 qwAddr, PDWORD64 pdwDisplacement, PIMAGEHLP_SYMBOL64_L  Symbol);

    static BOOL	bSymLoad;
    static char symName[1024];
    static IMAGEHLP_SYMBOL64_L *pSym = NULL;
    static pfnSymInitialize SymInit;
    static pfnSymGetSymFromAddr64 SymName;

    if (!bSymLoad)
        HMODULE hMod;			
        if ( (hMod = LoadLibrary(__T("Dbghelp.dll"))) &&
            (SymInit = (pfnSymInitialize) GetProcAddress(hMod, "SymInitialize")) &&
            (SymName = (pfnSymGetSymFromAddr64) GetProcAddress(hMod, "SymGetSymFromAddr64")))
            bSymLoad = SymInit(GetCurrentProcess(), NULL, true);
            pSym = (IMAGEHLP_SYMBOL64_L *) malloc(sizeof(IMAGEHLP_SYMBOL64_L) + 2000);

    if (bSymLoad)
        DWORD64  dwDisplacement = 0;
        pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64_L);
        pSym->MaxNameLength = 2000;

        if (SymName(GetCurrentProcess(), dwAddr, &dwDisplacement, pSym))
            return &pSym->Name[0];

    return NULL;

LONG CALLBACK VectoredExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo)
    CString strMsg;
    strMsg.Format("Exception code: 0x%x (%s)", ExceptionInfo->ExceptionRecord->ExceptionCode,
		Symbol((DWORD) ExceptionInfo->ExceptionRecord->ExceptionAddress) );

BOOL InitInstance()
    AddVectoredExceptionHandler(1, VectoredExceptionHandler);

It uses few symbol handler functions from Dbghelp.dll, which gives applications easy and portable access to the symbolic debugging information of an executable image.




Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: