我在 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
)作为仅用于测试目的的启动项目。
我已经实现了一个库来导入一些信息欧特克发明家 https://en.wikipedia.org/wiki/Autodesk_Inventor文档文件。发明家学徒 COM 服务器(Inventor Apprentice
在图片上)用于实现它,它是与。第一步,导入是在独立的本机 C++ 控制台应用程序中实现的,一切正常。然后它被改编为作为本机 C++ dll 在整个基础设施中使用(Import library
),然后调试地狱就开始了。
Symptoms
“调试坏了”。在调试版本中,调用以下 COM 方法后Import library
:
auto pComponentDefinitions = pDocument->GetComponentDefinitions();
C++ 代码中的断点不再被命中。即使我在另一个DLL的代码中设置断点,它也不会被命中。断点仍然显示为完整的红色圆圈,因此这与 PDB 问题无关。
应用程序本身继续执行,一段时间后我可以在 GUI 中看到数据导入的正确结果,这意味着Import library
已正确执行。之后,我可以暂停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() https://msdn.microsoft.com/en-us/library/f408b4et.aspx有问题的导入代码之前和之后。第一个被命中(如果调试尚未中断),但第二个未被命中。另一方面,调试器清楚地注意到它,因为它将以下消息写入输出窗口:
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 update 4。项目是在 x64 模式下构建的。使用.Net Framework v4.0。使用 Inventor 2015 中的 Inventor Apprentice。
实验表明:
- 当没有附加调试器时一切正常。
- 当使用仅本机调试时(通过
Service console app
或者在仅以本机模式附加到已运行的进程之后)。
- 在混合(即本机+托管)调试模式下,无论是否
GUI application
已通过调试启动或调试器已附加到工作进程。
- 在调试和发布模式下都存在问题,但表现不同。在调试构建中,会出现疯狂的调试问题(“调试损坏”),但在发布中,它只是在内部某处崩溃(“内部崩溃”)。
可以看到执行的运行的完整列表here https://docs.google.com/document/d/1nzMSU37gaVEbT43CY09gzPxzy4NwnhSzFAnjo_2tmQM/edit?usp=sharing.
主要问题
以前有人见过类似的行为吗?造成这种行为的原因可能是什么?有办法解决吗?