避免调试器搜索不需要的符号
上次更新时间:
- 2007 年 5 月 27 日
调试驱动程序时,您会遇到一个有趣的断点,只是让调试器在尝试加载您未拥有的驱动程序符号时停顿了很长时间,而这些符号对于手头的调试任务根本不重要。 这是怎么回事?
默认情况下,调试器会根据需要加载符号。 (这称为延迟符号加载或懒符号加载。)每当调试器执行需要显示符号的命令时,就会查找符号。 如果在当前上下文中设置了无效的监视变量(例如当前堆栈帧中不存在的函数参数或局部变量),则在上下文发生更改时,在断点上可能会发生这种情况。 如果只是错误键入符号名称或执行无效的调试器命令,调试器将开始查找匹配的符号,则也可能发生这种情况。
为什么这有时需要这么久? 这取决于符号名称是限定还是不限定。 限定的符号名称前面有包含符号的模块的名称,例如 myModule!myVar。 未限定的符号名称未指定模块名称,例如 myOtherVar。
对于限定名称,调试器将在指定的模块中查找符号,如果模块尚未加载,则加载模块(假设模块存在并包含符号)。 这发生得相当快。
对于非限定名称,调试器不“知道”哪个模块包含符号,因此它必须查找所有这些模块。 调试器首先检查所有已加载模块中的符号,如果无法在任何已加载模块中匹配到符号,调试器将继续搜索,方法是依次加载所有未加载的模块,首先从下游存储开始,最后到符号服务器(如果您在使用的话)。 显然,这可能需要很多时间。
如何防止自动加载不合格符号
SYMOPT_NO_UNQUALIFIED_LOADS 选项在搜索未限定符号时禁用或启用调试器自动加载模块。 设置 SYMOPT_NO_UNQUALIFIED_LOADS 并且调试器尝试匹配非限定符号时,它只搜索已加载的模块,并在无法匹配符号时停止搜索,而不是加载卸载的模块以继续其搜索。 此选项不会影响搜索符合条件的名称。
默认情况下,SYMOPT_NO_UNQUALIFIED_LOADS 处于关闭状态。 若要激活此选项,请使用 -snul 命令行选项,或者在调试器运行时,分别使用 .symopt+0x100 或 .symopt-0x100 打开或关闭该选项。
若要查看 SYMOPT_NO_UNQUALIFIED_LOADS 的效果,请尝试以下试验:
- 使用 -n 命令行选项激活干扰符号加载(SYMOPT_DEBUG),或者,如果调试器正在运行,请使用 .symopt+0x80000000 或 !sym 调试器扩展命令。 SYMOPT_DEBUG 指示调试器显示有关其搜索符号的信息,例如加载每个模块的名称;如果调试器找不到文件,则显示错误消息。
- 指示调试器评估不存在的符号(例如,类型 ?asdasdasd)。 调试器在搜索不存在的符号时应报告大量错误。
- 使用 .symopt+0x100 激活 SYMOPT_NO_UNQUALIFIED_LOADS。
- 重复步骤 2。 调试器应仅搜索加载的模块来查找不存在的符号,并且应更快地完成任务。
- 若要禁用 SYMOPT_DEBUG,请使用 .symopt-0x80000000 或 !sym quiet 调试器扩展命令。
许多选项可用于控制调试器加载和使用符号的方式。 有关符号选项的完整列表以及如何使用它们,请参阅 Windows 调试工具提供的联机文档中的“设置符号选项”。 最新版本的 Windows 调试工具包可从 Web 免费下载,也可以从 Windows DDK、平台 SDK 或客户支持诊断 CD 安装包。
你应该做什么?
- 若要加快符号搜索速度,请尽可能在断点和调试器命令中使用限定的名称。 如果想要查看已知模块中的符号,请使用模块名称对其进行限定;如果不知道符号的位置,请使用不限定的名称。 对于局部变量和函数参数,请使用 $ 作为模块名称(例如,$!MyVar)。
- 若要诊断符号加载缓慢的原因,请使用 -n 命令行选项激活干扰符号加载(SYMOPT_DEBUG),或者,如果调试器已在运行,请使用 .symopt+0x80000000 或 !sym 干扰 调试器扩展命令来激活干扰符号加载。
- 若要防止调试器在卸载的模块中搜索符号,请使用 -snul 命令行选项激活 SYMOPT_NO_UNQUALIFIED_LOADS,或者,如果调试器已在运行,请使用 .symopt+0x100。
- 若要显式加载调试会话所需的模块,请使用调试器命令,例如 .reload 或 ld。
另请参阅
适用于 Windows 的 调试工具