Visual Studio 调试器在混合调试模式下停止命中断点
Visual Studio debugger stops hitting breakpoints in mixed debugging mode
我在 MSVC2013 中混合调试时遇到严重问题。从本机 C++ DLL 调用 COM 方法后,调试器不再在断点处停止。
代码结构
上图是代码的整体结构。
我有一个解决方案,包含大约十个 C# 项目、大约五十个 C++ 本机项目和一个 C++/CLI 项目,作为托管世界和本机世界之间的桥梁。启动项目是一个C# WPF 项目(GUI Application
),它在内部调用C++/cli 项目(Bridge
),后者又调用各种原生C++ Dll(Various libraries
)。或者,我可以制作一个 C++ 控制台应用程序 (Service console app
) 作为仅用于测试目的的启动项目。
我已经实现了一个库来从 Autodesk Inventor document files. Inventor Apprentice COM server (Inventor Apprentice
on picture) is used to achieve it, which was freely downloaded alongside with Inventor View 2015 导入一些信息。作为第一步,导入是在独立的本机 C++ 控制台应用程序中实施的,一切正常。然后它被改编为在整个基础设施中作为原生 C++ dll (Import library
) 使用,调试地狱开始了。
症状
"debugging broken". 在调试版本中,在 Import library
中调用以下 COM 方法后:
auto pComponentDefinitions = pDocument->GetComponentDefinitions();
C++ 代码中的断点不再命中。即使我在另一个 DLL 的代码中设置断点,它也不会被命中。断点仍然显示为完整的红色圆圈,因此这与 PDB 问题无关。
应用程序本身继续执行,一段时间后我可以在 GUI 中看到正确的数据导入结果,这意味着 Import library
已正确执行。之后,我可以使用 Break All 按钮暂停 GUI Application
,在这种情况下,主线程显示深深地卡在 Inventor 的一个 dll (rse.dll) 中,这不可能是真的,因为该线程已经完成导入,甚至返回了正确的结果。
在输出 window 中,我可以看到以下消息,出现在有问题的 COM 方法调用期间(访问冲突在 Apprentice 中似乎很正常):
First-chance exception at 0x000007FEDD451F0C (rse.dll) in GUIApplication.exe: 0xC0000005: Access violation writing location 0x000007FFFDE3AFCC.
The Common Language Runtime cannot stop at this exception. Common causes include: incorrect COM interop marshalling and memory corruption. To investigate further use native-only debugging.
First-chance exception at 0x000007FEDD455F6C (rse.dll) in GUIApplication.exe: 0xC0000005: Access violation writing location 0x000007FFFDE3EE6C.
我试图在编译时将断点嵌入到代码中,方法是在有问题的导入代码前后插入 __debugbreak()。第一个被击中(如果调试尚未中断),但第二个没有。另一方面,调试器清楚地注意到它,因为它将以下消息写入 Output window:
The process hit a breakpoint the Common Language Runtime cannot continue from.
This may be caused by an embedded breakpoint in the native runtime or a breakpoint set in a can't-stop region.
To investigate further, use native-only debugging.
Google 对此诊断消息根本没有给出任何结果。听起来 MSVC 认为它正在调试托管代码,实际上是本机代码。
"crashes in call". 在发布构建的情况下,运行 处于混合调试模式的应用程序导致 rse.dll有问题的 COM 调用。
再现性
我使用 MSVC 2013 update 4。项目是在 x64 模式下构建的。使用 Net Framework v4.0。使用 Inventor 2015 的 Inventor Apprentice。
实验表明:
- 没有附加调试器时一切正常。
- 当使用纯本机调试时(通过
Service console app
或在纯本机模式下附加到已经 运行 进程之后),一切正常(包括调试)。
- 在混合(即本机 + 托管)调试模式下,无论
GUI application
是通过调试启动还是将调试器附加到工作进程,问题都会重现。
- debug和release模式都有问题,只是表现不同。在调试构建中出现了疯狂的调试问题 ("debugging broken"),但在发布中它只是在内部某处崩溃 ("crashes inside")。
完整的运行列表可见here。
主要问题
有没有人见过类似的行为?这种行为的原因可能是什么?有办法解决吗?
禁用 MSVC 的新托管调试引擎有助于解决此问题。可以通过转到工具 > 选项 > 调试 > 常规 > 勾选 "Use Managed Compatibility Mode".
来完成
在尝试找到该问题的解决方法时,我 post 编辑了 。 Hans Passant post 不仅提供了解决方法,而且还解决了我的主要问题。在 C++/CLI 互操作的情况下,新的调试引擎似乎无法正常工作。
P.S. 鉴于症状非常独特和疯狂,我决定 post 完整的问题和答案,希望这些信息将来可能会帮助一些遇到类似问题的人。
我在 MSVC2013 中混合调试时遇到严重问题。从本机 C++ DLL 调用 COM 方法后,调试器不再在断点处停止。
代码结构
上图是代码的整体结构。
我有一个解决方案,包含大约十个 C# 项目、大约五十个 C++ 本机项目和一个 C++/CLI 项目,作为托管世界和本机世界之间的桥梁。启动项目是一个C# WPF 项目(GUI Application
),它在内部调用C++/cli 项目(Bridge
),后者又调用各种原生C++ Dll(Various libraries
)。或者,我可以制作一个 C++ 控制台应用程序 (Service console app
) 作为仅用于测试目的的启动项目。
我已经实现了一个库来从 Autodesk Inventor document files. Inventor Apprentice COM server (Inventor Apprentice
on picture) is used to achieve it, which was freely downloaded alongside with Inventor View 2015 导入一些信息。作为第一步,导入是在独立的本机 C++ 控制台应用程序中实施的,一切正常。然后它被改编为在整个基础设施中作为原生 C++ dll (Import library
) 使用,调试地狱开始了。
症状
"debugging broken". 在调试版本中,在 Import library
中调用以下 COM 方法后:
auto pComponentDefinitions = pDocument->GetComponentDefinitions();
C++ 代码中的断点不再命中。即使我在另一个 DLL 的代码中设置断点,它也不会被命中。断点仍然显示为完整的红色圆圈,因此这与 PDB 问题无关。
应用程序本身继续执行,一段时间后我可以在 GUI 中看到正确的数据导入结果,这意味着 Import library
已正确执行。之后,我可以使用 Break All 按钮暂停 GUI Application
,在这种情况下,主线程显示深深地卡在 Inventor 的一个 dll (rse.dll) 中,这不可能是真的,因为该线程已经完成导入,甚至返回了正确的结果。
在输出 window 中,我可以看到以下消息,出现在有问题的 COM 方法调用期间(访问冲突在 Apprentice 中似乎很正常):
First-chance exception at 0x000007FEDD451F0C (rse.dll) in GUIApplication.exe: 0xC0000005: Access violation writing location 0x000007FFFDE3AFCC.
The Common Language Runtime cannot stop at this exception. Common causes include: incorrect COM interop marshalling and memory corruption. To investigate further use native-only debugging.
First-chance exception at 0x000007FEDD455F6C (rse.dll) in GUIApplication.exe: 0xC0000005: Access violation writing location 0x000007FFFDE3EE6C.
我试图在编译时将断点嵌入到代码中,方法是在有问题的导入代码前后插入 __debugbreak()。第一个被击中(如果调试尚未中断),但第二个没有。另一方面,调试器清楚地注意到它,因为它将以下消息写入 Output window:
The process hit a breakpoint the Common Language Runtime cannot continue from.
This may be caused by an embedded breakpoint in the native runtime or a breakpoint set in a can't-stop region.
To investigate further, use native-only debugging.
Google 对此诊断消息根本没有给出任何结果。听起来 MSVC 认为它正在调试托管代码,实际上是本机代码。
"crashes in call". 在发布构建的情况下,运行 处于混合调试模式的应用程序导致 rse.dll有问题的 COM 调用。
再现性
我使用 MSVC 2013 update 4。项目是在 x64 模式下构建的。使用 Net Framework v4.0。使用 Inventor 2015 的 Inventor Apprentice。 实验表明:
- 没有附加调试器时一切正常。
- 当使用纯本机调试时(通过
Service console app
或在纯本机模式下附加到已经 运行 进程之后),一切正常(包括调试)。 - 在混合(即本机 + 托管)调试模式下,无论
GUI application
是通过调试启动还是将调试器附加到工作进程,问题都会重现。 - debug和release模式都有问题,只是表现不同。在调试构建中出现了疯狂的调试问题 ("debugging broken"),但在发布中它只是在内部某处崩溃 ("crashes inside")。
完整的运行列表可见here。
主要问题
有没有人见过类似的行为?这种行为的原因可能是什么?有办法解决吗?
禁用 MSVC 的新托管调试引擎有助于解决此问题。可以通过转到工具 > 选项 > 调试 > 常规 > 勾选 "Use Managed Compatibility Mode".
来完成在尝试找到该问题的解决方法时,我 post 编辑了
P.S. 鉴于症状非常独特和疯狂,我决定 post 完整的问题和答案,希望这些信息将来可能会帮助一些遇到类似问题的人。