2012-09-25 15 views
25

次のC#コードは.NET4.0ではクラッシュするが、.NET2.0では正常に動作するというのは面白いことです。.NET4.0でAccessViolationExceptionをキャッチできない理由

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以降、システム例外のキャッチメカニズムが変更されている可能性があります。何か案は?

答えて

47

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

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

HandleProcessCorruptedStateExceptions attributeでこれらの例外をキャッチするメソッドにマーキングすることで、ケースバイケースで行うこともできます。

+0

偉大な答え。どうもありがとう!!!!この質問は長い間私を混乱させました。 –

+1

私はこの問題を1週間追跡していました!私が壊れた状態で便利にできることの1つは再起動です。 * 24時間稼働する必要があるコンソールアプリです。今度はそうなるでしょう。 – Andiih

+0

@Andiih破損したビットがそれを再起動するコードでない限り。私はこの目的のために外部ウォッチドッグを使用します。 –

3
[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; 
    }