若要在调试过程中检查程序,调试器必须能够访问托管堆栈帧并计算表达式。 以下几节描述调试器如何使用公共语言运行时 (CLR) 调试 API 来执行这些任务。
访问调用堆栈
以下列表提供了调试器如何访问托管堆栈帧的逐步说明。 调试对象进程必须停止才能访问堆栈帧。
调试器获取堆栈链的枚举数。 调试器为线程调用 ICorDebugThread::EnumerateChains 方法,从而访问该线程的堆栈链以获取 ICorDebugChainEnum 对象来枚举堆栈链。
调试器通过调用 ICorDebugChainEnum::Next 方法来循环访问堆栈链。
调试器通过调用 ICorDebugChain::EnumerateFrames 方法来获取链中堆栈帧的枚举数。
调试器通过调用 ICorDebugFrameEnum::Next 方法继续循环访问堆栈帧。
调试器可以选择获取 IP 地址。 调试器调用 ICorDebugILFrame::GetIP 方法以获取相对于堆栈帧函数开始位置的 IP 地址。
调试器可以选择获取有关堆栈帧的其他信息。 例如,调试器可以调用 ICorDebugFrame::GetFunctionToken 方法以获取堆栈帧所运行的代码的函数元数据标记。 调试器还可以调用 ICorDebugCode::GetCode 方法以获取表示堆栈帧所运行的代码的对象。
计算表达式
通过使用常规调试器所使用的相同机制,可以计算非托管本机代码中的表达式。
在托管代码中,调试器可以计算表达式,如下所示:
分析表达式。
调用调试 API 以访问表达式中的变量值以及调用表达式中的函数。
或者,调试器可以执行以下操作:
在全局函数中包含表达式并编译此函数。
调用调试 API(编辑并继续)以添加全局函数。
调用调试 API 以计算函数。
以下列表提供了调试器如何计算表达式的逐步说明。 在本方案中,表达式为 A + MyFunc(),其中假定 A 位于寄存器中,并且所调用的代码为托管本机代码。
调试器获取 A 的值。 调试器为要在其中计算表达式的堆栈帧调用 ICorDebugNativeFrame::GetLocalRegisterValue 方法。
通过为要在其中计算表达式的线程调用 ICorDebugThread::CreateEval 方法,调试器将创建计算对象。
通过调用 ICorDebugEval::CallFunction 方法,调试器将计算 MyFunc() 的值。
调试器将计算表达式。 通过使用在前两个步骤中获得的值,调试器将对表达式应用常量合并。