Why Accessviolationexception Cannot Be Caught by .Net4.0

Why AccessViolationException cannot be caught by .NET4.0

Yes, it changed in .NET 4. You cannot catch exceptions that indicate a corrupted state. This is because there's pretty much no guarantee that you can do anything at all when a corrupted state exception is thrown. There is practically no reason to want a process with corrupted state to continue executing.

For compatibility with older code, you can change this behaviour by adding the legacyCorruptedStateExceptionsPolicy element to app.config.

You can also do it on a case-by-case basis by marking methods where you want to catch these exceptions with the HandleProcessCorruptedStateExceptions attribute.

How to handle AccessViolationException

EDIT (3/17/2021)

Disclaimer: This answer was written in 2011 and references the original .NET Framework 4.0 implementation, NOT the open-source implementation of .NET.


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.

Is it possible to catch an access violation exception in .NET?

You shouldn't. An access violation is a serious problem: it is an unexpected attempt to write to (or read from) an invalid memory address. As John already clarified, the unmanaged DLL might already have corrupted the process memory before the access violation has been raised. This can have unpredicted effects on any part of the current process.

The safest thing to do is to possibly inform the user and then immediately exit.

Some more details: An access violation is an OS exception (a so-called SEH or structured exception handling exception). This is a different kind of exception than the managed CLR exceptions from System.Exception. You will rarely see SEH exceptions in purely managed code, but if one occurs, e.g. in unmanaged code, the CLR will deliver it to managed code where you are also able to catch it1.

However, catching SEH exceptions is mostly not a good idea. Further details are explained in the article Handling Corrupted State Exceptions in MSDN magazine where the following text it taken from:

The CLR has always delivered SEH exceptions to managed code using the same mechanisms as exceptions raised by the program itself. This isn't a problem as long as code doesn't attempt to handle exceptional conditions that it cannot reasonably handle. Most programs cannot safely continue execution after an access violation. Unfortunately, the CLR's exception handling model has always encouraged users to catch these serious errors by allowing programs to catch any exception at the top of the System.Exception hierarchy. But this is rarely the right thing to do.

1This was true until .NET 3.5. In .NET 4 the behavior has been changed. If you still want to be able to catch such kind of exceptions you would have to add legacyCorruptedState­­ExceptionsPolicy=true to the app.config. Further details in the articled linked above.

AccessViolationException not caught despite HandleProcessCorruptedStateExceptions

You forgot to insert a try/catch around table.Start().

[HandleProcessCorruptedStateExceptions] definitely needs a try/catch to catch that AccessViolationException.

So your code should be:

[HandleProcessCorruptedStateExceptions]
private static void StartTable(Table table) {
try
{
table.Start();
}
catch (AccessViolationException)
{
// Ignore
}
}

You can take a look at here or here for references.

What to do when AccessViolationException in .NET 4 app defies MSDN documented behavior?

The root cause is in fact "air space" due to crossing runtime environment from .NET 4 to .NET 2.

Also, it turns out SQL Server 2008 R2 SSIS Runtime likely has a double free memory bug in SQL logging subcomponent.

Access violation exception at 'Marshal.StructureToPtr' in Windows 7 + .NET 4.0 (Windows XP + .NET 3.5 works fine)

I didn't want to add an answer here as you already have solved your problem and what I'll say won't provide any answer to the problem you had, but it wouldn't fit well as a comment as I provide some code.
So I'm obliged to post it here as an answer.

You may already know it (and didn't wrote it that way so the code in your question is simpler), but I just wanted to say that a best practice that should be used everywhere when unmanaged memory is allocated, is to encapsulate the code in a try/finally block to ensure the memory is always freed, even if an exception is thrown:

private static void Test()
{
IntPtr ptrStruct = IntPtr.Zero;

try
{
Marshal.AllocHGlobal(0x100);

// Some code here
// At some point, an exception is thrown
throw new IndexOutOfRangeException();
}
finally
{
// Even if the exception is thrown and catch
// from the code that calls the Test() method,
// the memory will be freed.
if (ptrStruct != IntPtr.Zero)
{
Marshal.FreeHGlobal(ptrStruct);
}
}
}

try
{
Test();
}
catch (IndexOutOfRangeException)
{
// Catches the exception, so the program won't crash
// but it'll exit the Test() method, so the try/finally
// ensures it won't leave without freeing the memory
Debugger.Break();
}


Related Topics



Leave a reply



Submit