web-dev-qa-db-ja.com

AccessViolationExceptionが.NET4.0でキャッチできない理由

次の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;
}

上記のC#コードを.NET2.0に対してコンパイルすると、すべて正常に機能します。 .NET4.0に対してコンパイルするだけで、実行時にクラッシュします。

.NET4.0以降、システム例外キャッチメカニズムが変更されたのではないかと思います。何か案は?

28
Miles Chen

はい、.NET4で変更されました。破損した状態を示す例外をキャッチすることはできません。これは、破損状態の例外がスローされたときに、何でもできるという保証がほとんどないためです。破損した状態のプロセスの実行を継続する理由は事実上ありません。

古いコードとの互換性のために、 legacyCorruptedStateExceptionsPolicy 要素をapp.configに追加することで、この動作を変更できます。

HandleProcessCorruptedStateExceptions属性 を使用してこれらの例外をキャッチするメソッドをマークすることにより、ケースバイケースでそれを行うこともできます。

50
    [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;
    }
4
Gabriel