【问题标题】:A stack overflow in an unmanaged library causes a .NET app to crash非托管库中的堆栈溢出导致 .NET 应用程序崩溃
【发布时间】:2017-05-03 12:44:42
【问题描述】:

因为我经常不得不使用来自第三方的库——有时它们会导致我的应用程序崩溃——我用 C++ 制作了一个测试库。该库有意生成堆栈溢出(通过递归调用方法)。使用 .NET 4.6 制作的测试应用程序调用导出的方法...并崩溃。

  • 试接?将无法到达且没有任何效果。
  • AppDomain.UnhandledException?将无法到达且没有任何效果。
  • 在自己的 AppDomain 中执行方法?没有效果。

捕获 throw 引发的“正常”异常对我的测试应用程序来说没有问题。

我怎样才能捕捉到这种异常?

【问题讨论】:

标签: c# c++ .net crash unmanaged


【解决方案1】:

从 C# 的角度来看,您不会捕获异常。本机代码中的堆栈溢出非常糟糕。调用线程可能在堆栈上有半个对象,您无法展开它。

实际上,您的选择是暂停有问题的线程,这意味着 C++ 代码不会返回到 C#。这并不是直接致命的——当没有可用的 CPU 内核时,线程一直被操作系统挂起。但是互斥体将保持锁定状态等。

当有问题的线程被挂起时,你的 C# 代码应该对所有可以挽救的东西执行紧急保存。接下来,安排重启(Windows 任务计划程序可以在这里提供帮助),并强制终止整个进程。

这遗漏了一个“小”细节:捕获堆栈溢出并挂起该线程。这可能最好使用由 Windows 直接调用的 Vectored Exception Handler 来完成。在这个异常处理程序中,检查异常对象是否是堆栈溢出。如果是这样,那么您就有问题了,因为您现在正在一个线程上运行,该线程一直到它的最后一个堆栈页面(并且也可能几乎已满)。所以,你只做两件事:打电话给ResumeThread(helperThread),然后打电话给SuspendThread(GetCurrentThread())。辅助线程唤醒,回调C#发起紧急保存,然后调用TerminateProcess

【讨论】:

  • 另一个线程没有帮助 - 应用程序也会以同样的方式崩溃。所以我无法捕捉/检测错误。因此,我无法挂起线程或做任何其他事情。
  • @Deep-Sea:应用程序确实会崩溃,这是不可避免的。但是“崩溃”并不是魔术。它可能是 C++ 中的未定义行为,但它在 Win32 中已明确定义。 Vectored Exception Handler 管理崩溃。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-13
  • 1970-01-01
相关资源
最近更新 更多