Случайно возникающее AccessViolationException в GDI + - PullRequest
13 голосов
/ 01 апреля 2011

У нас проблема в том, что иногда возникает AccessViolationException, и простой групповой блок рисуется с белым фоном и красным крестом поверх него.Мы не можем воспроизвести эту ошибку надежно, она просто возникает время от времени.

Мы не делаем ничего особенного, мы просто показываем главное окно с меню, панель инструментов, групповое поле наГлавная панель и некоторые элементы управления гиперссылками внутри групповой рамки.

Из трассировки стека это кажется ошибкой в ​​Windows Forms или 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) 

Ответы [ 3 ]

1 голос
/ 15 июня 2014

Короче говоря.Я обнаружил, что в Dot.Net есть «ошибка», когда объекты перемещаются с помощью GC из одного места в другое в процессе оптимизации памяти или процесса дефрагментации.Обычно это происходит при отправке ссылки на массив управляемой памяти (или изображение) на неуправляемый фрагмент кода.Данные перемещаются в другое место, и поскольку неуправляемый код не знает об этом, он пытается получить доступ к «старому» расположению данных.Это происходит только в режиме Release, так как в режиме Debug оптимизация памяти отключена, поэтому ВСЕГДА отлаживайте в режиме Release, ме ...

К сожалению, нет способа отключить процесс дефрагментации GC.Вы можете попробовать вызвать GC.Collect () и дождаться его завершения, прежде чем вызывать вашу функцию GDI +, но это только улучшит ситуацию и не решит ее полностью.

Единственный способ, которым я смог обойти этозаключается в том, чтобы вручную заблокировать (закрепить) данные и освободить их после возвращения из неуправляемого кода, да, обратно в C ++.Изображения сложны, так как вам нужно найти точную ссылку на данные во всех классах и подклассах.

Надеюсь, это поможет.

0 голосов
/ 05 апреля 2011

мы сталкиваемся с подобной проблемой.У нас есть программное обеспечение, которое работает на многих машинах без проблем.На одном Windows XP SP 3 мы имеем следующее поведение:

  1. Приложение запускается и работает правильно
  2. Через некоторое время мы начинаем получать AccessViolationException из собственного кода GDI.Приложение прекращает рендеринг некоторых элементов управления или вылетает, если исключение не обрабатывается.

Есть несколько мест, откуда происходит нарушение, например:

1) Исключение: System.AccessViolationException
Сообщение. Попытка чтения или записи в защищенную память.Это часто указывает на то, что другая память повреждена.
Источник: 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)  

Код, похоже, не делает ничего необычного.Он рендерит изображение в буфер и затем вызывает: e.Graphics.DrawImageUnscaled (_bufferImage, 0, 0);Доступ к буферу не осуществляется никаким другим потоком.

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)

Здесь метод OnPaint не делает ничего, кроме рисования только одной строки.Перо (и его кисть), переданное DrawLine, конечно, хорошо инициализировано и не утилизировано.

0 голосов
/ 01 апреля 2011

Вы звонили GdiplusShutdown до того, как все было выпущено?Я задал похожий вопрос здесь , где я позвонил GdiplusShutdown до того, как мое растровое изображение было уничтожено, а также получило нарушение прав доступа

...