优雅地处理.NET Core中的损坏状态异常

时间:2018-02-08 09:56:04

标签: c# .net-core access-violation corrupted-state-exception

我基本上有一个重复question但是对于.NET Core。

我有Core控制台应用:

class Program
{
    static void DoSomeAccessViolation()
    {
        // if you have any questions about why this throws,
        // the answer is "42", of course

        var ptr = new IntPtr(42);
        Marshal.StructureToPtr(42, ptr, true);
    }

    [SecurityCritical]
    [HandleProcessCorruptedStateExceptions]
    static void Main(string[] args)
    {
        try
        {
            DoSomeAccessViolation();
        }
        catch (Exception ex)
        {
            Console.Error.WriteLine(ex);
        }
    }
}

我试图添加一个Settings.setting文件

<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="ConsoleApp2" GeneratedClassName="Settings1">
  <Profiles />
  <Settings>
    <Setting Name="legacyCorruptedStateExceptionsPolicy" Type="System.Boolean" Scope="Application">
      <Value Profile="(Default)">True</Value>
    </Setting>
  </Settings>
</SettingsFile>

我尝试根据docs设置环境变量:

C:\>set COMPlus_legacyCorruptedStateExceptionsPolicy=1
C:\>dotnet run

C:\>set COMPlus_legacyCorruptedStateExceptionsPolicy=true
C:\>dotnet run

(在Windows上)。但没有任何作用,应用程序总是崩溃而不打印异常。

3 个答案:

答案 0 :(得分:1)

我运行了你的代码,引发的异常是ExecutionEngineException。这是运行时中的致命错误,这意味着运行时无法进一步执行您的程序。你有理由不能抓住这个例外:你无法处理它。您的代码无法做任何事情来修复&#34;运行时并继续运行。

来自Microsoft docu:公共语言运行库的执行引擎中存在内部错误时引发的异常。 并且:此类型先前在运行时中指示了未指定的致命错误。运行时不再引发此异常,因此此类型已过时。

答案 1 :(得分:0)

按时间顺序,我一直在研究这个主题的某些背景...

dotnet / coreclr Issue #9045:剥离损坏的状态异常处理

dotnet / coreclr PR #10957:不遵守属性HandleProcessCorruptedStateExceptions

dotnet / coreclr Issue #19192:无法捕获托管代码中从本地Linux代码抛出的任何用户异常

我目前是SOL。 必须创建各种非托管包装来捕获外部CSE。

您可以尝试使用few more options,特别是FailFastOnCorruptedStateException与legacyCorruptedStateExceptionsPolicy组合。

答案 2 :(得分:0)

.net核心中唯一保留的是legacyCorruptedStateExceptionsPolicy行为。

要启用此功能,必须在过程开始之前将COMPlus_legacyCorruptedStateExceptionsPolicy环境变量设置为1。 但是,由于在.net移植过程中做出的决定,在.net核心中,与.net相比,它捕获的更少损坏状态异常:(

例如,如果将代码Marshal.StructureToPtr(42, (IntPtr)42, true);替换为Marshal.ReadInt32((IntPtr)42);(并设置环境变量),将成功生成并捕获AVE。

您可以阅读有关此问题的详细信息here

有关.net核心中损坏状态异常的总体说明:

  1. 要捕获其中的一部分,请在过程开始之前将COMPlus_legacyCorruptedStateExceptionsPolicy环境变量设置为1
  2. 如果您从本地电话获得CSE。尝试将异常处理移到那里(如果有源代码的话),或者尝试使用非托管包装器作为TylerY86 suggested
  3. 编写WatchDog程序以检查您的应用程序崩溃(如果重要的话)。 然后查看事件日志并分析故障转储...