13

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) 
Cœur
  • 34,719
  • 24
  • 185
  • 251
Steven
  • 141
  • 1
  • 4
  • I haven't seen this before, but I suppose that's to be expected. You say you can't reliably repro. The quick solution is probably to set the [`FlatStyle` property](http://msdn.microsoft.com/en-us/library/system.windows.forms.groupbox.flatstyle.aspx) of your `GroupBox` control to "System". It looks like the error is occurring when WinForms tries to draw the groupbox internally; if you let the system draw it, you'll bypass WinForms implementation & GDI+ altogether. That'll at least get you a working build to deploy while you figure out the real culprit. Maybe post some code to help us out there? – Cody Gray Apr 01 '11 at 08:01
  • First thing I should do is to fire up the Task Manager and display the count of User object and GDI objects to see if the app is leaking any of those. – Dan Byström Apr 04 '11 at 12:29
  • Are you using multiple threads in the calling code? – Beachwalker Jan 15 '13 at 17:45
  • I have experience the problem, some time ago. I seem to recall that it was operating system dependant and was triggered by a service pack which was then resolved later by a .NET service pack. – Jamie Clayton Jan 04 '14 at 15:21

3 Answers3

1

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.

LW001
  • 2,217
  • 4
  • 27
  • 34
Gilad
  • 2,766
  • 5
  • 27
  • 40
0

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

Community
  • 1
  • 1
default
  • 10,975
  • 8
  • 63
  • 100
0

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:

  1. The application starts and runs correctly
  2. After some time, we start getting AccessViolationException from GDI native code. The application stops rendering some controls or crashes if the exception is not handled.

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

at System.Drawing.SafeNativeMethods.Gdip.GdipDrawImageI(HandleRef graphics, HandleRef image, Int32 x, Int32 y)
at System.Drawing.Graphics.DrawImage(Image image, Int32 x, Int32 y)
at System.Drawing.Graphics.DrawImageUnscaled(Image image, Int32 x, Int32 y)
at Aga.Controls.Tree.TreeViewAdv.DrawTree(PaintEventArgs e)
at Aga.Controls.Tree.TreeViewAdv.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)  

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)

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.Drawing.Graphics.DrawLine(Pen pen, Point pt1, Point pt2)
at SomeMyNamespace.SomeMyControl.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.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.ContainerControl.WndProc(Message& m)
at System.Windows.Forms.UserControl.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.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

Here OnPaint method does not do anything other than painting just one line. Pen (and its Brush) passed to DrawLine is certainly well initialized and not disposed.

joe
  • 7,779
  • 8
  • 49
  • 75
zuraff
  • 1,223
  • 1
  • 12
  • 18