HOWTO Automatically Catch Problems While Debugging

Suppose to have the ability to add dozens of breakpoints into your program main error detection points, whenever you start a debugging session.

This should allow you to easily track down some hidden/unnoticed problems.

For example, suppose to have a C function like the below one:

__MYOBJECTDATA * WINAPI MYOBJGetPtr (HANDLE hMyObject)
{
    __MYOBJECTDATA *pObj;

    pObj = (__MYOBJECTDATA *) hMyObject;
    __try
    {
        if ((pObj != NULL) && !<verify *pOBJ>)
            pObj = NULL;
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        pObj = NULL;
    }
    return pObj;
}

This function transforms a handle to a data ptr, only if it passes the proper verification steps.

It is written to properly process 3 values’ types:

  • valid handles
  • NULL handles
  • invalid handles (not NULL values that don’t pass the verification process).

This last type may usually hide some upstream error, and it usually needs immediate attention to track & fix the problem.
Usually, we can fix them quickly, if we catch them.

Writing a Debugger-Aware code

Windows gives us the ability to easily write Debugger-Aware code by using a couple of system API:

  • IsDebuggerPresent() – it tests if a debugging session is active.
  • DebugBreak() – it triggers a debugger breakpoint.

Now we can update our function, to trigger a debugger breakpoint on every invalid handle values.

__MYOBJECTDATA * WINAPI MYOBJGetPtr (HANDLE hMyObject)
{
    __MYOBJECTDATA *pObj;

    pObj = (__MYOBJECTDATA *) hMyObject;
    __try
    {
        if ((pObj != NULL) && !<verify *pOBJ>)
            pObj = NULL;
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        pObj = NULL;
    }
#ifdef _DEBUG
    if (IsDebuggerPresent () && (hMyObject != NULL) && (pObj == NULL))
        DebugBreak ();
#endif
    return pObj;
}

With only 4 lines of code, the debug version of this function is now clever enough to call us for any invalid handle values that occurred, only when a debugging session is active.

This will allow us, to backstep from the function for the call stack, and fix any improper handle usage.

 

I find the reach of this hint quite intriguing…