范围和符号组

符号组包含一组符号,便于作为一个整体进行有效操作。 可以手动创建和填充符号组,也可以根据词法范围内的符号(例如局部变量和函数参数)自动生成和更新。 接口 IDebugSymbolGroup 用于表示符号组。

有两种方法可以创建符号组。 CreateSymbolGroup 返回空符号组,当前词法范围的符号组由 GetScopeSymbolGroup 返回。

注意 从当前作用域生成的符号组是局部变量的快照。 如果目标中发生任何执行过程,数据符号可能不再准确。 此外,如果当前作用域发生更改,符号组将不再表示 当前 范围(因为它将继续表示为其创建的范围)。

可以使用 AddSymbol 将符号添加到符号组中,并使用 RemoveSymbolByIndexRemoveSymbolByName 将其删除。 OutputAsType 方法指示调试器处理符号数据时使用不同的符号类型。

注意 范围符号的值可能不准确。 具体而言,计算机体系结构和编译器优化可能会阻止调试器准确确定符号的值。

符号项信息是符号的说明,包括符号的位置和类型。 若要在模块中查找符号的此信息,请使用 IDebugSymbols3::GetSymbolEntryInformation。 若要查找符号组中符号的此信息,请使用 IDebugSymbolGroup2::GetSymbolEntryInformation。 关于符号条目的信息,请参阅 DEBUG_SYMBOL_ENTRY

以下方法返回有关符号组中符号的信息:

如果符号存储在寄存器或调试器引擎已知的内存位置中,则可以使用 WriteSymbol 更改其值。

如果符号包含其他符号,则符号是 符号。 例如,结构包含其成员。 如果符号包含在另一个符号中,则符号是 子符号 。 符号可以是父符号和子符号。 每个符号组别都有一个平面结构,其中包含父符号及其子级。 每个符号都有 深度 -- 符号组中没有父级符号的深度为零,每个子符号的深度大于其父符号的深度。 父符号的子级可能会存在于符号组中,也可能不会。 当子符号存在于符号组中时,父符号被称作展开的符号。 若要在符号组中添加或删除符号的子级,请使用 ExpandSymbol

GetNumberSymbols 返回符号组中的符号数。 符号组中符号的 索引 是标识号;索引范围从零到符号数减去 1。 每次向符号组添加或从符号组中删除符号时(例如,展开符号)时,符号组中所有符号的索引可能会更改。

可以使用 GetSymbolParameters 找到符号参数,包括有关父子关系的信息。 此方法返回 DEBUG_SYMBOL_PARAMETERS 结构。

可以使用 OutputSymbols 方法将符号组中的符号打印到调试器的输出流。

范围

当前作用域当前本地上下文确定调试器引擎公开的局部变量。 范围有三个组件:

  1. 堆栈帧。

  2. 当前指令。

  3. 寄存器上下文。

如果堆栈帧位于调用堆栈的顶部,则当前指令是导致最后一个事件的指令。 否则,当前指令是导致下一个更高的堆栈帧的函数调用。

GetScopeSetScope 方法可用于获取和设置当前范围。 事件发生时,当前作用域设置为事件的范围。 可以使用 ResetScope 将当前范围重置为最后一个事件的范围。

线程上下文

线程上下文是在切换线程时 Windows 保留的状态。 这类似于寄存器上下文,只是有一些仅内核处理器状态是寄存器上下文的一部分,而不是线程上下文。 在内核模式调试期间,此额外状态可用作寄存器。

线程上下文由 ntddk.h 中定义的 CONTEXT 结构表示。 此结构依赖于平台,其解释取决于有效的处理器类型。 GetThreadContextSetThreadContext 的方法可用于获取和设置线程上下文。