Question

I have a C# app that uses some unmanaged GDI+ functionality and I get an (unmanaged?) exception:

Log Name: Application
Source: .NET Runtime
Date: 7/1/2013 9:14:58 AM
Event ID: 1026
Task Category: None
Level: Error
Keywords: Classic
User: N/A
Computer: sth
Description:
Application: sth
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.AccessViolationException

The stack trace is :

at System.Drawing.SafeNativeMethods+Gdip.IntGdipDisposeImage(System.Runtime.InteropServices.HandleRef)
at System.Drawing.SafeNativeMethods+Gdip.IntGdipDisposeImage(System.Runtime.InteropServices.HandleRef)
at System.Drawing.Image.Dispose(Boolean)
at System.Drawing.Image.Dispose()
at “..()
at Aspose.Cells.Charts.Chart.ToImage(System.IO.Stream, Aspose.Cells.Rendering.ImageOrPrintOptions)

Can I prevent it from crashing entirely? I have tried using a catch statement without arguments, but sth tells me it's not enough. I have made my own C++ DLL with these faulty pieces of code and nothing seems to work, unless the DLL throw sth:

__declspec(dllexport) void __cdecl Function1(void) // This doesn't get caught.
{
    char *chrs = new char[1000];
    delete []chrs;
    delete []chrs;
}

__declspec(dllexport) void __cdecl Function3(void) // This doesn't get caught.
{
    try
    {
        MessageBox(NULL, L"AAA", L"Caption", MB_OK);
        char *chrs = NULL;
        chrs[0] = 'a';
    }
    catch(...)
    {
        MessageBox(NULL, L"BBB", L"Caption", MB_OK); // I get no messagebox here... (probably it doesn't get caught)
    }
}

__declspec(dllexport) void __cdecl Function2(void) // This gets caught as a .NET Exception.
{
    throw "Oh My!";
}

So, can I do sth to prevent my EXE from crashing?

EDIT

Also, does System.AccessViolationException means that this is a managed exception? If, yes, I wonder why I don't catch it... My code is wrapped inside try{}catch(){}...

EDIT2

My guess is that the GDI+ corrupts the heap and the CLR detects it later-on and throws an exception. But it can't be caught because it's not thrown from inside a try block. Can I do sth in this case?

Was it helpful?

Solution

Some exceptions are nasty, they indicate a very major mishap in your program. Some are so nasty that it is completely impossible to recover from the condition. This site's name falls in that category. So does ExecutionEngineException. These are so nasty that the odds that a catch block can still execute properly are zero. They instantly terminate your program.

System.AccessViolationException is just a hair below that ultra-nasty, let's call it super-nasty. It is an exception that's generated by the processor when it finds out that it cannot execute code anymore. Deadly to a program of course. There are several possible reasons for it, the most typical ones are an invalid machine code instruction or access to a memory location that is not readable or writable. Heap corruption is a very typical cause of a memory access problem.

Catching the exception is technically possible since exception handling jerks the processor away from the code that can't execute anymore and forces it to continue elsewhere. So the CLR isn't forced to terminate the program. It is however a very strong sign that the state of your program is heavily corrupted. This kind of corruption is very rarely isolated.

Seeing it bomb when you dispose a bitmap heavily points to such kind of corruption. With a high likelihood that it is an unmanaged heap that got corrupted, used by the GDI+ to store the pixel data for the bitmap. Such kind of corruption is not typically caused by GDI+ itself, it can be other unmanaged code that runs in your program that's spraying junk into the heap when it fumbles a pointer.

You can spin the wheel of fortune and catch the exception. But with high odds that your program continues bombing on AVs whenever it accesses data on that broken heap. Bombing on an OutOfMemoryException is also very possible. After all, you meant to release unmanaged memory and that didn't happen. This happens later, where it can do a lot more damage and gives fewer ways to diagnose what caused it. Like the finalizer, it is going to bomb as well. And that's fatal, the CLR terminates the program when a finalizer throws an unhandled exception.

Catching it is really just a bandaid, you really need to tackle the root cause. Which is however hard, the location in the code where the heap damage trips the AV is never close to the code that caused the corruption. In other words, suspecting that GDI+ is the cause is not going to help you find the cause. It is in fact the least likely cause, GDI+ is one heavily tested chunk of code, exercised billions of times every day.

If you don't suspect unmanaged code in your own process then isolate the problem by testing your program on another machine. Could be as simple as a bad shell extension that gets loaded into your process when you use OpenFileDialog for example. If you do then writing unit tests for any unmanaged code you use in your program is typically required. Good luck with it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top