这实际上是一个已解决的问题,但它是如此深奥,我想我会与其他用户分享它。
也许其他人可能会提出原因?
无论如何,我正在开发一个用托管 C++ 编写的“混合模式”.NET 应用程序,但与现有的本机库有大量链接。
问题是,未处理的托管异常最终成为 Win32 访问冲突。我的意思是,我不会显示带有未处理托管异常的漂亮 .NET 对话框,而是会收到旧样式的“未处理的 win32 异常发生在...”消息。
有趣的是:如果我在调试器中启动应用程序,那么抛出的托管异常会被正确拾取。即,调试器向我显示了这条线。
但是,当正常执行时,它会变成这种访问冲突。在那个时候附加调试器会产生很少的有用信息(它甚至不会显示合理的堆栈跟踪)。
因此,对我来说,这表明在未处理的托管异常到达异常处理程序之前,本机代码中正在发生某些事情。
因此,无论如何,我通过将我的项目与 Visual Studio 2008 生成的全新 C++ 托管项目进行比较,设法解决了这个问题。
解决方法是执行以下操作:
将 /SUBSYSTEM 标志(项目属性->链接器->系统->子系统)从/SUBSYSTEM:WINDOWS更改为“未设置”
从使用旧式 WinMain() 切换到使用新式 main()。
即它曾经是
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
现在是
int main(array<System::String ^> ^args)
[为什么我使用这个奇怪的_tWinMain?这是多年前 Visual Studio .NET IDE 在您创建示例混合模式 Windows 应用程序时生成的。它一直运行良好(直到现在),所以我从不费心改变它。_tWinMain 只是 WinMain 的一个宏]
我做了这个改变,问题就消失了。未处理的 .NET 异常现在可以正确捕获,因此我现在可以实际调试它们。
我还对干净的示例 C++ 应用程序进行了反向更改,并证明这是原因。
所以,我的问题是,到底发生了什么?
只是我使用的是旧风格的 WinMain 而不是新的main(array <String^>^)
?
我是否应该将此报告给 Microsoft(有人会关心 ;-))吗?