We've got the problem that sometimes an AccessViolationException
occurs and a simple group box gets drawn with white background and a red cross on top of it. We can't reproducable this bug reliably, it just occurs from time to time.
We don't do anything special, we're just showing a main window with a menu, toolbar, the group box on the main panel and some hyperlink controls inside the group box.
From the stack trace it seems to be a bug in Windows Forms or GDI+:
System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at System.Drawing.SafeNativeMethods.Gdip.GdipDrawLineI(HandleRef graphics, HandleRef pen, Int32 x1, Int32 y1, Int32 x2, Int32 y2)
at System.Drawing.Graphics.DrawLine(Pen pen, Int32 x1, Int32 y1, Int32 x2, Int32 y2)
at System.Windows.Forms.GroupBox.DrawGroupBox(PaintEventArgs e)
at System.Windows.Forms.GroupBox.OnPaint(PaintEventArgs e)
at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer, Boolean disposeEventArgs)
at System.Windows.Forms.Control.WmPaint(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.GroupBox.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
To make long story short. I found out that there is a ""bug"" in Dot.Net where objects are moved by the GC from one place to the other as part of memory optimization or Defragmentation process. This usually happens when sending a reference of a managed memory array (or image) to an un-managed piece of code. The data is being moved to a different location and as the un-managed code is not aware of this it tries to access the "old" location of the data. This only happens in Release mode as in Debug mode memory optimization is switched off so ALWAYS debug in Release mode, meh...
Unfortunately, there is no way to turn off the GC defragmentation process. You can try and call the GC.Collect() and wait for it to finish before calling your GDI+ function but this will only improve the situation and not solve it completely.
The only way I was able to bypass this is to manually lock (pin) the data and release it after returned from the un-managed code, yes, back to C++. Images are tricky as you need to find the exact reference to the data in all the classes and sub-classes.
Hope this helps.
Did you call GdiplusShutdown before everything was released? I asked a similar question here where I called GdiplusShutdown before my Bitmap was destroyed and also got access violation
we are running into similar problem. We have software which runs on many machines without issues. On one Windows XP SP 3 we have the following behavior:
There are a few places where the violation comes from, e.g.:
1) Exception: System.AccessViolationException
Message: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Source: System.Drawing
The code does not seem to do anything unusual. It renders an image to a buffer then calls: e.Graphics.DrawImageUnscaled(_bufferImage, 0, 0); The buffer is not accessed by any other thread.
2)
Here
OnPaint
method does not do anything other than painting just one line. Pen (and its Brush) passed toDrawLine
is certainly well initialized and not disposed.