Visual Studio调试器在混合调试模式下停止命中断点

我在MSVC2013中进行混合调试存在严重问题。 从本机C ++ DLL调用COM方法后,调试器不再停止在断点处。

代码结构

方案

上图显示了代码的整体结构。

我有一个解决方案,包含大约10个C#项目,大约50个C ++本机项目,以及一个C ++ / CLI项目,作为托管和本地世界之间的桥梁。 启动项目是一个C#WPF项目( GUI Application ),它在内部调用C ++ / cli项目( Bridge ),后者又调用各种本机C ++ Dll( Various libraries )。 或者,我可以将C ++控制台应用程序( Service console app )作为启动项目,仅用于测试目的。

我已经实现了一个库来从Autodesk Inventor文档文件中导入一些信息。 Inventor Apprentice COM服务器(图片上的Inventor Apprentice )用于实现它,可以与Inventor View 2015一起免费下载。 作为第一步,导入是在独立的本机C ++控制台应用程序中实现的,一切正常。 然后它被改编为在整个基础架构中用作本机C ++ DLL( Import library ),并且调试地狱开始了。

症状

“调试坏了”。 在调试版本中,在Import library调用以下COM方法之后:

 auto pComponentDefinitions = pDocument->GetComponentDefinitions(); 

C ++代码中的断点不再受到影响。 即使我在另一个DLL的代码中设置断点,它也不会被命中。 断点仍然可视化为完整的红色圆圈,因此这与PDB问题无关。 应用程序本身继续执行,一段时间后我可以在GUI中看到正确的数据导入结果,这意味着Import library已正确执行。 之后,我可以使用Break All按钮暂停GUI Application ,在这种情况下,主线程显示在Inventor的一个dll(rse.dll)中,这可能不是真的,因为该线程已完成导入并且甚至已返回正确的结果。

在“输出”窗口中,我可以看到以下消息,在有问题的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窗口:

 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认为它正在调试托管代码,这实际上是原生代码。

“在电话中崩溃”。 在发布版本的情况下,在混合调试模式下运行应用程序会导致在有问题的COM调用期间rse.dll内部崩溃。

再生性

我使用MSVC 2013更新4.项目是在x64模式下构建的。 使用Net Framework v4.0。 使用Inventor 2015的Inventor Apprentice。 实验表明:

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

可以在此处查看所执行的完整运行列表。

主要问题

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

禁用MSVC的新托管调试引擎有助于解决此问题。 可以通过转到工具>选项>调试>常规>勾选“使用托管兼容模式”来完成。


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

PS鉴于这些症状非常独特和疯狂,我决定在答案中发布完整的问题,希望这些信息可以帮助将来有类似问题的人。