使用托管调试助手诊断错误

更新: 2008 年 7 月

托管调试助手 (MDA) 是调试辅助程序,它与公共语言运行时 (CLR) 结合工作以提供关于运行时状态的信息。这些助手生成关于无法通过其他方式捕获的运行时事件的信息性消息。可以使用 MDA 隔离在托管代码和非托管代码之间转换时发生的难以发现的应用程序 Bug。可通过向 Windows 注册表添加注册表项或设置环境变量,来启用或禁用所有的 MDA。可使用应用程序配置设置来启用特定 MDA。可以在应用程序的配置文件中为某些单独的 MDA 设置附加配置设置。由于将在加载运行时时分析这些配置文件,因此必须在托管应用程序启动之前启用 MDA。不能为已经启动的应用程序启用 MDA。

d21c150d.alert_note(zh-cn,VS.90).gif说明:

启用 MDA 后,即使不在调试器下执行代码,MDA 也会处于活动状态。如果在调试器不存在时引发 MDA 事件,尽管这不是未处理的异常,事件消息也会出现在未处理的异常对话框中。若要避免出现该对话框,请在调试环境中未执行代码时移除 MDA 启用设置。

d21c150d.alert_note(zh-cn,VS.90).gif说明:

在 Visual Studio 集成开发环境 (IDE) 中执行代码时,可以避免针对特定 MDA 事件出现的异常对话框。为此,请在“调试”菜单上单击“异常”。(如果“调试”菜单不包含“异常”命令,请在“工具”菜单上单击“自定义”添加该命令。)在“异常”对话框中,展开“托管调试助手”列表,然后清除相应 MDA 的“引发”复选框。例如,若要避免出现 contextSwitchDeadlock MDA 的异常对话框,请在“托管调试助手”列表中清除该 MDA 名称旁边的“引发”复选框。也可以使用此对话框启用 MDA。

下表列出 .NET Framework 附带的 MDA。

asynchronousThreadAbort MDA

bindingFailure MDA

callbackOnCollectedDelegate MDA

contextSwitchDeadlock MDA

dangerousThreadingAPI MDA

dateTimeInvalidLocalFormat MDA

dirtyCastAndCallOnInterface MDA

disconnectedContext MDA

dllMainReturnsFalse MDA

exceptionSwallowedOnCallFromCom MDA

failedQI MDA

fatalExecutionEngineError MDA

gcManagedToUnmanaged MDA

gcUnmanagedToManaged MDA

illegalPrepareConstrainedRegion MDA

invalidApartmentStateChange MDA

invalidCERCall MDA

invalidFunctionPointerInDelegate MDA

invalidGCHandleCookie MDA

invalidIUnknown MDA

invalidMemberDeclaration MDA

invalidOverlappedToPinvoke MDA

invalidVariant MDA

jitCompilationStart MDA

loaderLock MDA

loadFromContext MDA

marshalCleanupError MDA

封送 MDA

memberInfoCacheCreation MDA

moduloObjectHashcode MDA

nonComVisibleBaseClass MDA

notMarshalable MDA

openGenericCERCall MDA

overlappedFreeError MDA

pInvokeLog MDA

pInvokeStackImbalance MDA

raceOnRCWCleanup MDA

Reentrancy

releaseHandleFailed MDA

reportAvOnComRelease MDA

streamWriterBufferedDataLost MDA

virtualCERCall MDA

默认情况下,.NET Framework 会为所有托管调试器激活 MDA 的子集。通过单击“调试”菜单上的“异常”并展开“托管调试助手”列表可以查看 Visual Studio 中的默认集合。

启用和禁用 MDA

可使用注册表项、环境变量和应用程序配置设置,启用和禁用 MDA。若要使用应用程序配置设置,就必须启用注册表项或环境变量。

在 Visual Studio 2005 和更高版本中,启用宿主进程后,不能禁用默认集合中的 MDA 或启用不在默认集合中的 MDA。宿主进程是默认启用的,因此必须将其显式禁用。

若要在 Visual Studio 中禁用宿主进程,请执行下列操作:

  1. 在“解决方案资源管理器”中选择一个项目。

  2. 在“项目”菜单上单击“属性”。

    出现“项目设计器”窗口。

  3. 单击“调试”选项卡。

  4. 在“启用调试器”部分中,清除“启用 Visual Studio 宿主进程”复选框。

但是,禁用宿主进程会影响性能。通过阻止 Visual Studio 在收到 MDA 通知时显示 MDA 对话框,可以无需禁用 MDA。为此,请单击“调试”菜单上的“异常”,展开“托管调试助手”列表,然后为单个 MDA 选中或清除“引发”复选框。

使用注册表项启用和禁用 MDA

可通过在 Windows 注册表中添加 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\MDA 子项启用 MDA。请将下面的示例复制到一个名为“MDAEnable.reg”的文本文件中:

Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework]
"MDA"="1"

在命令提示符处执行 MDAEnable.reg 文件,以在计算机上启用 MDA。若要禁用 MDA,请将下面的示例复制到一个名为“MDADisable.reg”的文本文件中:

Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework]
"MDA"="0"

然后从命令提示符运行 MDADisable.reg 文件。

默认情况下,即使未添加该注册表项,有些 MDA 也会在运行附加到调试器的应用程序时启用。pInvokeStackImbalance MDAinvalidApartmentStateChange MDA 即属于此类助手。可以按上面的描述运行 MDADisable.reg 文件来禁用这些助手。

使用环境变量启用和禁用助手

还可以通过环境变量 COMPLUS_MDA 控制 MDA 激活。环境变量将重写注册表项。该字符串是区分大小写的分号分隔的 MDA 名称的列表或其他特殊控制字符串。在托管或非托管调试器下启动将默认启用一组 MDA。这是通过在环境变量或注册表项的值前面隐式附加调试器下默认启用的分号分隔的 MDA 的列表来实现的。特殊控制字符串如下:

  • 0 -- 停用所有 MDA。

  • 1 - 从应用程序名称.mda.config 读取 MDA 设置。

  • managedDebugger -- 显式激活在调试器下启动托管可执行文件时隐式激活的所有 MDA。

  • unmanagedDebugger -- 显式激活在调试器下启动非托管可执行文件时隐式激活的所有 MDA。

如果存在冲突的设置,则最近的设置重写先前的设置:

  • COMPLUS_MDA=0 禁用所有 MDA,包括在调试器下隐式启用的那些 MDA。

  • COMPLUS_MDA=gcUnmanagedToManaged 启用 gcUnmanagedToManaged 以及在调试器下隐式启用的任何 MDA。

  • COMPLUS_MDA =0;gcUnmanagedToManaged 启用 gcUnmanagedToManaged,但是禁用那些将在调试器下隐式启用的 MDA。

使用特定于应用程序的配置设置启用和禁用 MDA

可以在应用程序的 MDA 配置文件中单独地启用、禁用和配置某些助手。若要使用用于配置 MDA 的应用程序配置文件,则必须设置 MDA 注册表项或 COMPLUS_MDA 环境变量。应用程序配置文件通常与应用程序的可执行文件 (.exe) 位于同一目录。该文件名采用应用程序名称.mda.config 的形式;例如,notepad.exe.mda.config。在应用程序配置文件中启用的助手可能包含专门设计用于控制该助手的行为的属性或元素。下面的示例演示如何启用和配置封送 MDA

<mdaConfig>
  <assistants>
    <marshaling>
      <methodFilter>
        <match name="*"/>
      </methodFilter>
      <fieldFilter>
        <match name="*"/>
      </fieldFilter>
    </marshaling>
  </assistants>
</mdaConfig>

这些设置启用和配置 Marshaling MDA,对于应用程序中每个托管到非托管的转换,该 MDA 发出描述正在被封送处理为非托管类型的托管类型的信息。Marshaling MDA 具有更大的灵活性,能够分别筛选 <methodFilter> 和 <fieldFilter> 子元素中提供的方法和结构字段的名称。

有关特定于每个单独的 MDA 的设置的更多信息,请参见该 MDA 的文档。

MDA 输出

MDA 输出类似于下面的示例,此示例显示了来自 pInvokeStackImbalance MDA 的输出。

A call to PInvoke function 'MDATest!MDATest.Program::StdCall' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.

请参见

其他资源

调试和分析应用程序

修订记录

日期

修订记录

原因

2008 年 7 月

增加了有关避免出现 ContextSwitchDeadlock 消息的说明。

客户反馈。