How to handle AccessViolationException

2018-12-31 14:33发布

问题:

I am using a COM object (MODI) from within my .net application. The method I am calling throws a System.AccessViolationException, which is intercepted by Visual Studio. The odd thing is that I have wrapped my call in a try catch, which has handlers for AccessViolationException, COMException and everything else, but when Visual Studio (2010) intercepts the AccessViolationException, the debugger breaks on the method call (doc.OCR), and if I step through, it continues to the next line instead of entering the catch block. Additionally, if I run this outside of the visual studio my application crashes. How can I handle this exception that is thrown within the COM object?

MODI.Document doc = new MODI.Document();
try
{
    doc.Create(sFileName);
    try
    {
        doc.OCR(MODI.MiLANGUAGES.miLANG_ENGLISH, false, false);
        sText = doc.Images[0].Layout.Text;
    }
    catch (System.AccessViolationException ex)
    {
        //MODI seems to get access violations for some reason, but is still able to return the OCR text.
        sText = doc.Images[0].Layout.Text;
    }
    catch (System.Runtime.InteropServices.COMException ex)
    {
        //if no text exists, the engine throws an exception.
        sText = \"\";
    }
    catch
    {
        sText = \"\";
    }

    if (sText != null)
    {
        sText = sText.Trim();
    }
}
finally
{
    doc.Close(false);

    //Cleanup routine, this is how we are able to delete files used by MODI.
    System.Runtime.InteropServices.Marshal.FinalReleaseComObject(doc);
    doc = null;
    GC.WaitForPendingFinalizers();
    GC.Collect();
    GC.WaitForPendingFinalizers();

}

回答1:

In .NET 4.0, the runtime handles certain exceptions raised as Windows Structured Error Handling (SEH) errors as indicators of Corrupted State. These Corrupted State Exceptions (CSE) are not allowed to be caught by your standard managed code. I won\'t get into the why\'s or how\'s here. Read this article about CSE\'s in the .NET 4.0 Framework:

http://msdn.microsoft.com/en-us/magazine/dd419661.aspx#id0070035

But there is hope. There are a few ways to get around this:

  1. Recompile as a .NET 3.5 assembly and run it in .NET 4.0.

  2. Add a line to your application\'s config file under the configuration/runtime element: <legacyCorruptedStateExceptionsPolicy enabled=\"true|false\"/>

  3. Decorate the methods you want to catch these exceptions in with the HandleProcessCorruptedStateExceptions attribute. See http://msdn.microsoft.com/en-us/magazine/dd419661.aspx#id0070035 for details.


EDIT

Previously, I referenced a forum post for additional details. But since Microsoft Connect has been retired, here are the additional details in case you\'re interested:

From Gaurav Khanna, a developer from the Microsoft CLR Team

This behaviour is by design due to a feature of CLR 4.0 called Corrupted State Exceptions. Simply put, managed code shouldnt make an attempt to catch exceptions that indicate corrupted process state and AV is one of them.

He then goes on to reference the documentation on the HandleProcessCorruptedStateExceptionsAttribute and the above article. Suffice to say, it\'s definitely worth a read if you\'re considering catching these types of exceptions.



回答2:

Add the following in the config file, and it will be caught in try catch block. Word of caution... try to avoid this situation, as this means some kind of violation is happening.

<configuration>
   <runtime>
      <legacyCorruptedStateExceptionsPolicy enabled=\"true\" />
   </runtime>
</configuration>


回答3:

Compiled from above answers, worked for me, did following steps to catch it.

Step #1 - Add following snippet to config file

<configuration>
   <runtime>
      <legacyCorruptedStateExceptionsPolicy enabled=\"true\" />
   </runtime>
</configuration>

Step #2

Add -

[HandleProcessCorruptedStateExceptions]

[SecurityCritical]

on the top of function you are tying catch the exception

source: http://www.gisremotesensing.com/2017/03/catch-exception-attempted-to-read-or.html



回答4:

You can try using AppDomain.UnhandledException and see if that lets you catch it.

**EDIT*

Here is some more information that might be useful (it\'s a long read).