在调试过程中,控制程序的过程包括在托管代码中设置断点、单步执行托管代码和非托管代码,以及处理首次异常和第二次异常。 以下几节描述调试器如何使用公共语言运行时 (CLR) 调试 API 来执行这些任务。
在托管代码中设置断点
以下列表提供了如何在托管代码中设置断点的分步说明:
调试器获取给定函数的模块对象。 调试器通过元数据接口调用 ICorDebugAppDomain::GetModuleFromMetaDataInterface 方法来获取函数模块的 ICorDebugModule 对象。
调试器通过调用 ICorDebugModule::GetFunctionFromToken 方法来获取给定函数的函数对象。
调试器通过调用 ICorDebugFunction::GetILCode 方法来获取给定函数的代码对象。
调试器通过以特定偏移量调用 ICorDebugCode::CreateBreakpoint 方法在托管代码中创建断点。 CreateBreakpoint 返回 ICorDebugBreakpoint 的一个实例。 断点是在活动状态下创建的。
调试器通过为当前调试对象进程调用 ICorDebugController::Continue 方法继续执行进程。
当线程到达断点时,调试 API 通过调用 ICorDebugManagedCallback::Breakpoint 回调来通知调试器。
单步执行托管代码和非托管代码
以下列表提供了有关调试器如何单步执行托管代码的分步说明:
在给定要在其中进行单步执行的线程的情况下,调试器创建一个分档器。 调试器为正在单步执行的线程调用 ICorDebugThread::CreateStepper 方法。 或者,调试器可以为相对于其进行单步执行的帧调用 ICorDebugFrame::CreateStepper 方法。 假定在创建分档器时进程已停止。
调试器通过调用 ICorDebugStepper::Step 方法来单步执行线程。
调试器通过为当前调试对象进程调用 ICorDebugController::Continue 方法继续执行进程。
调试 API 通知调试器该步骤已完成。 调试 API 为调试器已向运行时注册的对象调用 ICorDebugManagedCallback::StepComplete 方法。
调试器通过调用 ICorDebugStepper::Step 方法再次单步执行线程。
调试器通过为当前调试对象进程调用 ICorDebugController::Continue 方法继续执行进程。
以下列表描述了针对非托管代码的单步执行替代方法:
调试器会选择性地在本机代码中跳过单步执行。 调试器调用 ICorDebugStepper::StepOut 方法跳过本机代码单步执行,直到重新激活上一帧为止。 当重新进入托管代码时,调试 API 会调用 ICorDebugManagedCallback::StepComplete 方法。
调试器会选择性地单步执行到托管代码的下一部分。 调试器调用 ICorDebugStepper::Step 方法,以便在重新进入上一个托管代码帧或者非托管代码调用新的托管代码时将控制权返回给调试器。
调试器通过为当前调试对象进程调用 ICorDebugController::Continue 方法继续执行进程。
调试 API 通过调用 ICorDebugUnmanagedCallback::DebugEvent 方法通知调试器它正在单步执行非托管代码。
处理异常
以下列表提供了有关如何处理首次异常和第二次异常的分步说明:
CLR 通知调试器发生首次异常。 调试 API 调用调试器已向运行时注册的 ICorDebugManagedCallback 接口中的 ICorDebugManagedCallback::Exception 方法。
调试器获取有关异常的信息。 调试器调用传入回调的 ICorDebugThread 对象中的 ICorDebugThread::GetCurrentException 方法,以便获取异常对象 (ICorDebugValue)。
调试器为该异常获取 ICorDebugObjectValue 对象。 调试器调用 QueryInterface 方法以获取异常的 ICorDebugObjectValue 对象。
调试器通过调用 ICorDebugObjectValue::GetClass 方法获取引发的异常对象的类。
调试器决定忽略异常并继续。
CLR 通知调试器发生第二次异常。 调试 API 调用 ICorDebugManagedCallback::Exception 方法,并指定该异常是第二次异常。
用户确定该异常无关紧要。 调试器为当前调试对象线程调用 ICorDebugThread::ClearCurrentException 方法。 此方法会清除异常并防止引发异常。
调试器通过为当前调试对象进程调用 ICorDebugController::Continue 方法继续执行进程。