2012-09-25 19 views
25

È davvero interessante che il seguente codice C# si blocca su .NET 4.0 ma funzioni correttamente su .NET 2.0.Perché AccessViolationException non può essere catturato da .NET4.0

C# codice

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(); 
} 

codice C

extern "C" __declspec(dllexport) int ExceptionTest() 
{ 
    IUnknown* pUnk = NULL; 
    pUnk->AddRef(); 
    return 0; 
} 

Se la compilazione del codice C# sopra contro .NET2.0, tutto funziona bene ++. La sua compilazione solo su .NET4.0 lo renderà irreversibile in fase di runtime.

Sospetto che il meccanismo di cattura delle eccezioni di sistema sia stato modificato da .NET 4.0. Qualche idea?

risposta

47

Sì, è stato modificato in .NET 4. Non è possibile rilevare eccezioni che indicano uno stato danneggiato. Questo perché non c'è praticamente alcuna garanzia che tu possa fare qualcosa quando viene lanciata un'eccezione di stato corrotta. Non vi è praticamente alcuna ragione per desiderare che un processo con stato corrotto continui ad essere eseguito.

Per compatibilità con codice precedente, è possibile modificare questo comportamento aggiungendo l'elemento legacyCorruptedStateExceptionsPolicy a app.config.

È inoltre possibile farlo caso per caso contrassegnando i metodi in cui si desidera rilevare queste eccezioni con HandleProcessCorruptedStateExceptions attribute.

+0

Ottima risposta. Molte grazie!!!! Questa domanda mi ha confuso per molto tempo. –

+1

Ho seguito questo problema per una settimana! L'unica cosa che posso fare utilmente con il mio stato corrotto è il riavvio. È un'applicazione per console che * dovrebbe * essere in esecuzione 24 ore al giorno. Adesso lo farà. – Andiih

+0

@Andiih a meno che i bit danneggiati non siano il codice che lo riavvierà. Userò watchdog esterni per questo scopo. –

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; 
    } 
Problemi correlati