Debugging Tools for Windows

指定模块和函数所有者

!analyze !owner 扩展命令使用名为Triage.ini 的文件来决定调试器遇到的符号的所有者。

使用这些扩展命令时,函数或模块的标识会显示在"Followup"之后。

Triage.ini 是在Windows调试工具包安装目录下的\triage 子目录中的一个文本文件。Windows调试工具包中有一个Triage.ini 文件的示例。

警告 如果在已有的Windows调试工具包目录下升级新版本,会将目录下的所有文件覆盖掉,包括Triage.ini 。修改或替换掉Triage.ini 文件之后,最好将它保存一份拷贝到其他目录中。重新安装调试器后,就可以使用备份的Triage.ini 来覆盖默认的。

Triage.ini 文件的格式

虽然Triage.ini文件用于帮助确定中断到调试器中的函数的所有者,文件中的 "owner" 字符串却可以是对调试有益的任何值。该字符串可以是编写或维护代码的人的名字,或者当某个模块或函数出错时的简短的操作流程说明。

文件中每一行都具有下面的语法。

Module[!Function]=Owner 

可以在模块或函数名的末尾添加一个星号(*)作为通配符。

所有者字符串中不能加入空格。如果存在空格,则它们都会被忽略。

关于该语法的更多信息,查看特殊Triage.ini语法

下面是一个triage.ini文件示例。

module1=Person1
module2!functionA=Person2
module2!functionB=Person3
module2!funct*=Person4
module2!*=Person5
module3!singleFunction=Person6
mod*!functionC=Person7

Triage.ini !owner

将模块或函数名传递给!owner扩展命令时,调试器在"Followup"后显示模块或函数的所有者。

下例使用了上面例子中的Triage.ini 文件。

0:000> !owner module2!functionB
Followup:  Person3

根据这个文件,"Person3"拥有module2!functionB,"Person4"拥有module2!funct*。这两个字符串都能和传递给!owner 的参数匹配,所以使用了更完整的匹配。

Triage.ini 和!analyze

使用!analyze扩展命令时,调试器在堆栈中查找顶层的异常帧(top faulting frame),并尝试确定该帧的模块和函数的所有者。如果找到,则会显示所有者信息。

如果调试器没有找到所有者,则会继续根据下面的堆栈帧来查找,直到调试器找到所有者或所有的堆栈都被检查过了。

如果找到了所有者,则在"Followup"后显示他的名字。如果调试器搜索了整个堆栈也没有找到任何信息,则不会显示名字。

下面的示例使用了上面例子中的Triage.ini

假设第一个堆栈帧是MyModule!someFunction。调试器在Triage.ini文件中没有找到MyModule 。然后,它会继续查找堆栈中的第二帧。

假设第二帧是module3!anotherFunction。调试器找到了一条关于module3的信息,但是该模块中没有和anotherFunction 匹配的信息。所以调试器继续查找第三帧。

假设第三帧是module2!functionC。调试器首先查找能精确匹配的信息但是未找到。所以会截掉函数名并在Triage.ini 中找到了module2!funct*。这个匹配结束搜索,因为调试器确认了所有者是"Person4"。

调试器会显示类似下面的输出。

0:000> !analyze
*******************************************************************************
*                                                                             *
*                        Exception Analysis                                   *
*                                                                             *
*******************************************************************************

Use !analyze -v to get detailed debugging information.

Probably caused by : module2 ( module2!functionC+15a )

Followup: Person4
---------

更加完整的匹配比短的匹配优先级更高。但是,相对于函数名,模块名称的匹配总是首选。如果Triage.ini 文件中没有module2!funct*,调试器会选择module2!* 来匹配。如果module2!funct*module2!* 都没有,则会选择mod*!functionC 匹配。

特殊Triage.ini 语法

如果省略掉感叹号和函数名,并在模块名后加上!*,则表示指定模块中所有函数。如果该模块中的某个函数也被单独指明了,则更精确的那个具有优先权。

如果使用"default"作为模块名或函数名,它等同于通配符。例如,nt!*nt!default 相同,default*!*相同。

如果找到一个匹配,但是等号右边是ignore ,则调试器使用堆栈中的下一帧来继续查找。

可以在所有者名字前加上last_maybe_ 。该前缀在运行!analyze 时给予所有者更少的优先权。调试器会在使用maybe_ 匹配之前先用其他定义来匹配。调试器同样会先选择maybe_的匹配,然后再选择last_ 匹配。

示例 Triage.ini

Windows调试工具包中包含一个Triage.ini的示例。可以在该文件中增加需要的模块和函数所有者。如果不想要全局性的预设值,将该文件开头的default=MachineOwner 行删除。

Build machine: CAPEBUILD