2011-04-01 37 views
13

Tenemos el problema de que a veces se produce un AccessViolationException y se dibuja un cuadro de grupo simple con fondo blanco y una cruz roja en la parte superior. No podemos reproducir este error de manera confiable, solo ocurre de vez en cuando.AccessViolationException que se produce aleatoriamente en GDI +

No hacemos nada especial, solo mostramos una ventana principal con un menú, una barra de herramientas, el cuadro de grupo en el panel principal y algunos controles de hipervínculos dentro del cuadro de grupo.

Desde el seguimiento de la pila que parece que hay un error en Windows Forms o 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) 
+0

No he visto esto antes, pero supongo que es de esperar. Usted dice que no puede reproducir de manera confiable. La solución rápida probablemente sea establecer la propiedad ['FlatStyle'] (http://msdn.microsoft.com/en-us/library/system.windows.forms.groupbox.flatstyle.aspx) de su control' GroupBox' para "Sistema". Parece que el error se está produciendo cuando WinForms intenta dibujar el groupbox internamente; si deja que el sistema lo dibuje, omitirá la implementación de WinForms y GDI + por completo. Eso al menos te dará una versión funcional para desplegar mientras descubres al verdadero culpable. Tal vez publicar un código para ayudarnos a salir? –

+0

Lo primero que debo hacer es iniciar el Administrador de tareas y mostrar el recuento de objetos de usuario y objetos GDI para ver si la aplicación tiene alguna de esas. –

+0

¿Está utilizando múltiples hilos en el código de llamada? – Beachwalker

Respuesta

0

¿Has llamado a GdiplusShutdown antes de que todo fue puesto en libertad? Hice una pregunta similar here donde llamé GdiplusShutdown antes de que mi mapa de bits se destruyera y también obtuve la infracción de acceso

0

, nos encontramos con un problema similar. Tenemos software que se ejecuta en muchas máquinas sin problemas. Por un Windows XP SP 3 tenemos el siguiente comportamiento:

  1. la aplicación se inicia y se ejecuta correctamente
  2. Después de algún tiempo, que comienza a recibir AccessViolationException de código nativo GDI. La aplicación deja de renderizar algunos controles o se bloquea si no se maneja la excepción.

Hay algunos lugares donde la violación proviene de, por ejemplo .:

1) Excepción: System.AccessViolationException
mensaje: Intento de leer o escribir en la memoria protegida. Esto a menudo es una indicación de que otra memoria está corrupta.
Fuente: 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) 

El código no parece hacer nada inusual. Representa una imagen en un búfer y luego llama: e.Graphics.DrawImageUnscaled (_bufferImage, 0, 0); No se accede al búfer por ningún otro hilo.

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) 

método Aquí OnPaint no hacer otra cosa que pintar sólo una línea nada. La pluma (y su pincel) pasada a DrawLine está bien inicializada y no eliminada.

1

Para acortar la historia. Descubrí que hay un "error" en Dot.Net donde los objetos son movidos por el GC de un lugar a otro como parte de la optimización de la memoria o el proceso de desfragmentación. Esto generalmente ocurre cuando se envía una referencia de una matriz de memoria administrada (o imagen) a un fragmento de código no administrado. Los datos se están moviendo a una ubicación diferente y como el código no administrado no tiene conocimiento de esto, intenta acceder a la ubicación "antigua" de los datos. Esto solo ocurre en modo Release, ya que en Debug mode, la optimización de memoria está apagada, así que SIEMPRE depura en modo Release, meh ...

Desafortunadamente, no hay forma de desactivar el proceso de desfragmentación del GC. Puede intentar llamar a GC.Collect() y esperar a que termine antes de llamar a su función GDI +, pero esto solo mejorará la situación y no la resolverá por completo.

La única forma en que pude omitir esto es bloquear manualmente (fijar) los datos y liberarlos después de devolverlos desde el código no administrado, sí, volver a C++. Las imágenes son complicadas ya que necesita encontrar la referencia exacta de los datos en todas las clases y subclases.

Espero que esto ayude.

+0

¡Qué carga de tonterías totales y absolutas! Esto no es un error de .net, es por diseño. –

Cuestiones relacionadas