托管 CLR 时如何捕获 ***Exception 并从中恢复

Posted

技术标签:

【中文标题】托管 CLR 时如何捕获 ***Exception 并从中恢复【英文标题】:How to catch and recover from ***Exception when hosting CLR 【发布时间】:2018-12-17 18:23:07 【问题描述】:

我了解从 .net2.0 开始 ***Exception 不再可捕获。但是人们提到了托管 CLR 时规则的异常,在这种情况下,可以处理并从此类异常中恢复。

这是有道理的,因为我托管 CLR 以在本机服务中执行托管代码/脚本,并且我不希望草率的脚本代码终止我的服务。相反,我希望能够从此类事件中恢复并从那时起将行为不端的脚本代码列入黑名单。

但我没有找到有关如何执行此操作的详细信息。

注意事项: [1] 我使用 C++/CLI 混合程序集作为桥接 dll 将我的本机服务连接到 dotnet,而不是使用其 COM 接口“显式托管 CLR”。

【问题讨论】:

销毁并重新创建 AppDomain? @PepitoSh 我使用 C++/CLI 混合程序集作为桥接 dll 将我的本机服务连接到 dotnet,并且由于性能原因,托管代码在默认应用程序域中运行,所以我想我无法销毁并重新创建默认 appdomain? 最简单的解决方案是不要编写耗尽堆栈的代码..而不是尝试解决问题,如果可以,尝试从源头解决它 如果栈溢出不是bug造成的,但你确实需要更大的栈,你可以提前调整它的大小。查看详情:***.com/questions/2556938/… 如果您通过 C++/CLI 偷偷访问 CLR,那么您并没有真正自己托管 CLR,您无法访问 CLR 托管选项。相反,您只是强制在您的进程中加载​​自托管 CLR。没有捷径 - 如果您想托管 CLR,那么您需要完成实际托管它的所有工作。 【参考方案1】:

我不知道这将在多大程度上适用于 .NET Framework(无论是实际自托管还是使用 C++/CLI),但请考虑使用 Win32 的 _resetstkoflw()

简而言之 - 你的程序应该在 SEH __except 处理程序中调用 _resetstkoflw()(这与 C++ 的 catch 块不同,并且绝对不能从 C++ 异常处理程序中调用 _resetstkoflw()!) - 这个假设您的程序中受影响的线程在进入 CLR 之前在 C/C++/本机代码中启动,而不是 CLR 创建的线程,这就是溢出的线程。

但是,我不知道如何在 CLR 创建的线程上使用 _resetstkoflw()。也许您可以拦截每个创建的线程并调用设置 SEH __try/__except 块然后重新进入 __try 内的 CLR 的 C/C++/native 代码? (假设that the interception of the creation of managed threads is even possible)。

【讨论】:

以上是关于托管 CLR 时如何捕获 ***Exception 并从中恢复的主要内容,如果未能解决你的问题,请参考以下文章

CLR 在调用 c++ 函数时如何避免重击?

托管和非托管

是否在CLR上运行非托管Visual C ++?

重温CLR(十五) 托管堆和垃圾回收

CLR 调试体系结构

是否可以捕获或隐藏非托管异常窗口?