为啥 AccessViolationException 不能被 .NET4.0 捕获

Posted

技术标签:

【中文标题】为啥 AccessViolationException 不能被 .NET4.0 捕获【英文标题】:Why AccessViolationException cannot be caught by .NET4.0为什么 AccessViolationException 不能被 .NET4.0 捕获 【发布时间】:2012-09-25 10:38:04 【问题描述】:

下面的 C# 代码在 .NET4.0 上会崩溃,但在 .NET2.0 上可以正常工作,这真的很有趣。

C# 代码

class Program

    static void Main(string[] args)
    
        try
        
            ExceptionTest();
            Console.WriteLine("Done!");
        
        catch (Exception e)
        
            Console.WriteLine("Error !!!");
            Console.WriteLine(e.Message);
        
    

    [DllImport("badapp")]
    private static extern int ExceptionTest();

C++ 代码

extern "C" __declspec(dllexport) int ExceptionTest()

    IUnknown* pUnk = NULL;
    pUnk->AddRef();
    return 0;

如果针对 .NET2.0 编译上述 C# 代码,一切正常。只有针对 .NET4.0 进行编译才会使其在运行时崩溃。

我怀疑自 .NET4.0 以来系统异常捕获机制已更改。有什么想法吗?

【问题讨论】:

【参考方案1】:

是的,它在 .NET 4 中发生了变化。您无法捕获指示损坏状态的异常。这是因为当一个损坏的状态异常被抛出时,几乎不能保证你可以做任何事情。实际上没有理由希望状态已损坏的进程继续执行。

为了与旧代码兼容,您可以通过将 legacyCorruptedStateExceptionsPolicy 元素添加到 app.config 来更改此行为。

您也可以根据具体情况使用HandleProcessCorruptedStateExceptions attribute 标记要捕获这些异常的方法。

【讨论】:

我已经关注这个问题一周了!我可以对损坏的状态有用的一件事是重新启动。它是一个应该每天 24 小时运行的控制台应用程序。现在它会的。 @Andiih 除非损坏的位是重新启动它的代码。为此,我会使用外部看门狗。 谢谢。我们也有一个外部看门狗(已经有一段时间了),但这可以在可能的情况下更快地重启。【参考方案2】:
    [HandleProcessCorruptedStateExceptions]
    public static unsafe int LenghtPoint(this IntPtr point)
    
        //por optimizar
        byte* bytePoint = (byte*)point.ToPointer();
        byte auxByte;
        int length = 1;
        bool encontrado = false;
        while (!encontrado)
        

            try
            

                auxByte = bytePoint[length];
                length++;
            
            catch (System.AccessViolationException)
            
                length--;
                encontrado = true;

            
        
        return length;
    

【讨论】:

以上是关于为啥 AccessViolationException 不能被 .NET4.0 捕获的主要内容,如果未能解决你的问题,请参考以下文章

为啥 DataGridView 上的 DoubleBuffered 属性默认为 false,为啥它受到保护?

为啥需要softmax函数?为啥不简单归一化?

为啥 g++ 需要 libstdc++.a?为啥不是默认值?

为啥或为啥不在 C++ 中使用 memset? [关闭]

为啥临时变量需要更改数组元素以及为啥需要在最后取消设置?

为啥 CAP 定理中的 RDBMS 分区不能容忍,为啥它可用?