Controlling a Program During Debugging

During debugging, controlling a program consists of setting breakpoints in managed code, stepping through managed and unmanaged code, and handling first-chance and second-chance exceptions. The following sections describe how a debugger uses the common language runtime (CLR) debugging API to perform these tasks.

Setting a Breakpoint in Managed Code

The following list provides a step-by-step description of how a breakpoint is set in managed code:

Stepping Through Managed and Unmanaged Code

The following list provides a step-by-step description of how a debugger single-steps through managed code.

  1. The debugger creates a stepper, given the thread in which the single-step is to occur. The debugger calls the ICorDebugThread::CreateStepper method for the thread that is being stepped. Alternatively, the debugger can call the ICorDebugFrame::CreateStepper method for the frame relative to which the stepping is to occur. It is assumed that the process is stopped when the stepper is created.

  2. The debugger steps the thread by calling the ICorDebugStepper::Step method.

  3. The debugger continues execution of the process by calling the ICorDebugController::Continue method for the current debuggee process.

  4. The debugging API informs the debugger that the step has completed. The debugging API calls the ICorDebugManagedCallback::StepComplete method for the object that the debugger had registered with the runtime.

  5. The debugger steps the thread again by calling the ICorDebugStepper::Step method.

  6. The debugger continues execution of the process by calling the ICorDebugController::Continue method for the current debuggee process.

The following list describes stepping alternatives with unmanaged code:

  • The debugger optionally skips stepping in native code. The debugger calls the ICorDebugStepper::StepOut method to skip native code stepping until the previous frame is reactivated. The debugging API calls the ICorDebugManagedCallback::StepComplete method when the managed code is reentered.

  • The debugger optionally steps into the next section of managed code. The debugger calls the ICorDebugStepper::Step method so that control is returned to the debugger when the previous managed code frame is reentered or when the unmanaged code calls new managed code.

  • The debugger continues execution of the process by calling the ICorDebugController::Continue method for the current debuggee process.

  • The debugging API informs the debugger that it is stepping into unmanaged code by calling the ICorDebugUnmanagedCallback::DebugEvent method.

Handling Exceptions

The following list provides a step-by-step description of how first-chance and second-chance exceptions are handled:

  1. The CLR informs the debugger that a first-chance exception has occurred. The debugging API calls the ICorDebugManagedCallback::Exception method on the ICorDebugManagedCallback interface that the debugger registered with the runtime.

  2. The debugger obtains information about the exception. The debugger calls the ICorDebugThread::GetCurrentException method on the ICorDebugThread object it was passed in the callback to obtain an exception object (ICorDebugValue).

  3. The debugger obtains the ICorDebugObjectValue object for the exception. The debugger calls the QueryInterface method to obtain the ICorDebugObjectValue object for the exception.

  4. The debugger obtains the class of the exception object that was thrown by calling the ICorDebugObjectValue::GetClass method.

  5. The debugger decides to ignore the exception and just continues.

  6. The CLR informs the debugger that a second-chance exception has occurred. The debugging API calls the ICorDebugManagedCallback::Exception method and specifies that the exception is a second-chance exception.

  7. The user decides that the exception is inconsequential. The debugger calls the ICorDebugThread::ClearCurrentException method for the current debuggee thread. This method clears the exception and prevents the exception from being thrown.

  8. The debugger continues execution of the process by calling the ICorDebugController::Continue method for the current debuggee process.

See Also

Other Resources

CLR Debugging Overview

Debugging (Unmanaged API Reference)