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。 实验表明:

  1. 没有附加调试器时一切正常。
  2. 当使用纯本机调试时(通过 Service console app 或在纯本机模式下附加到已经 运行 进程之后),一切正常(包括调试)。
  3. 在混合(即本机 + 托管)调试模式下,无论 GUI application 是通过调试启动还是将调试器附加到工作进程,问题都会重现。
  4. debug和release模式都有问题,只是表现不同。在调试构建中出现了疯狂的调试问题 ("debugging broken"),但在发布中它只是在内部某处崩溃 ("crashes inside")。

完整的运行列表可见here

主要问题

有没有人见过类似的行为?这种行为的原因可能是什么?有办法解决吗?

禁用 MSVC 的新托管调试引擎有助于解决此问题。可以通过转到工具 > 选项 > 调试 > 常规 > 勾选 "Use Managed Compatibility Mode".

来完成

在尝试找到该问题的解决方法时,我 post 编辑了 。 Hans Passant post 不仅提供了解决方法,而且还解决了我的主要问题。在 C++/CLI 互操作的情况下,新的调试引擎似乎无法正常工作。

P.S. 鉴于症状非常独特和疯狂,我决定 post 完整的问题和答案,希望这些信息将来可能会帮助一些遇到类似问题的人。