2008-10-08 11 views
5

Tengo una aplicación que parece arrojar excepciones solo después de que se haya cerrado el programa. Y es muy inconsistente. (Todos sabemos cuán divertidos son los errores inconsistentes ...)Excepciones lanzadas (errores encontrados) Después de la terminación del programa

Supongo que hay un error durante el proceso de limpieza. Pero estos errores de lectura/escritura de memoria parecen indicar algo incorrecto en mi uso del código "inseguro" (¿punteros?).

Lo que me interesa es ¿cuál es el mejor método para depurar estas situaciones?
¿Cómo se depura un programa que ya se ha cerrado?
Estoy buscando un punto de partida para analizar un problema mayor.

Estos errores parecen presentarse de varias formas (algunos tiempo de ejecución, algunos de depuración):

 
1: .NET-BroadcastEventWindow.2.0.0.0.378734a.0: Application.exe - Application Error
The instruction at "0x03b4eddb" referenced memory at "0x00000004". The memory could not be "written". 2: Application.vshost.exe - Application Error
The instruction at "0x0450eddb" referenced memory at "0x00000004". The memory could not be "written". 3: Application.vshost.exe - Application Error
The instruction at "0x7c911669" referenced memory at "0x00000000". The memory could not be "read". 4: Application.vshost.exe - Application Error
The instruction at "0x7c910ed4" referenced memory at "0xfffffff8". The memory could not be "read".

Respuesta

4

Si su aplicación es multiproceso, podría estar recibiendo errores de subprocesos de trabajo que no terminan correctamente e intentan acceder a los objetos eliminados.

+0

Sí, es multiproceso. Me doy cuenta de que los desarrolladores tienden a evitar las aplicaciones de gran cantidad de subprocesos, pero mi aplicación puede tener varios gráficos animados ejecutándose al mismo tiempo, por lo que el número de subprocesos es significativo. – PersistenceOfVision

+0

Los subprocesos múltiples no son un pecado en sí mismo, pero es más probable que un hilo errante (o dos) se descarguen en la distancia mucho después de que el proceso haya finalizado. Verifique los procesos en ejecución después de cerrar su aplicación. –

+0

@ [PersistenceOfVision]: si sospecha que los hilos secundarios son los culpables, puede reemplazarlos con SafeThreads - http://www.codeproject.com/KB/threads/SafeThread.aspx –

1

que he visto suficiente de errores al igual que este recientemente. Mis problemas se relacionaron con la forma en que el CRT (C Runtime) que interactúa con el tiempo de ejecución de .NET limpia un proceso de cierre. Mi aplicación es complicada por el hecho de que es C++, pero permite agregar complementos COM, algunos escritos en C#.

Para solucionar esto, creo que vas a necesitar usar depuración nativa. Visual Studio (configurado para la depuración en modo mixto) o WinDbg. Consulte cómo utilizar el servidor de símbolos público de Microsoft para descargar los PDB para los componentes de Windows: necesita esos símbolos.

Muchos de nuestros problemas fueron con .NET (terrible) soporte de cliente COM. Digo horrible, ya que no hace recuento de referencia correctamente (sin mucho trabajo en el extremo del desarrollador). Los objetos COM no estaban referenciados, contados hasta cero hasta que se realizó la recogida de basura. A menudo, esto configura problemas de temporización durante el apagado: los objetos COM se limpian mucho después de lo debido.

1

Una palabra más elegante para "inconsistente" es "no determinista". ¿Y qué sucede de manera no determinista en el entorno .NET? Destrucción de objetos.

Cuando esto me sucedió, el culpable estaba en la clase que escribí para envolver llamadas inseguras a una API externa. Puse código de limpieza en el destructor de la clase, esperando que se llamara al código cuando el objeto saliera del alcance. Pero no es así como funciona la destrucción de objetos en .NET. Cuando un objeto sale del alcance, se pone en la cola del finalizador, y su destructor no se llama hasta que el finalizador lo solucione. Es posible que no haga esto hasta que el programa finalice. Si esto sucede, el resultado se parecerá mucho a lo que está describiendo aquí.

Una vez que hice que mi clase implementara IDisposable, y explícitamente llamé Dispose() al objeto cuando terminé con el problema, desapareció el problema. (Otra ventaja de implementar IDisposable es que puede crear una instancia de su objeto al comienzo de un bloque using y tener la certeza de que Dispose() se obtendrá cuando el código abandone el bloque.)

0

probar esto para forzar el error que ocurra mientras está bajo el control del programa

//set as many statics as you can to null; 
    GC.Collect(); 
    GC.WaitForPendingFinalizers(); 
} //exit main 
0

El error dejó de aparecer después de usar el código sugerido:

GC.Collect(); 
GC.WaitForPendingFinalizers(); 
6

he tenido este problema utilizando el componente AcrobarReader COM. De vez en cuando, después de la salida de la aplicación tenía "Application.vshost.exe - Application Error" "la memoria no se podía leer". GC.Collect() y WaitForPendingFinalizers() no ayudaron.

Mi google-fu me llevó a esta página: http://support.microsoft.com/kb/826220. Modifiqué el método 3 para mi caso.

Usando el explorador de procesos encontré que AcroPDF.dll no se lanza antes de la última línea en la función Principal. Entonces, aquí vienen las llamadas API.

DLLImports (DLLImport está en System.Runtime.InteropServices espacio de nombres):

<DllImport("kernel32.dll", EntryPoint:="GetModuleHandle", _ 
     SetLastError:=True, CharSet:=CharSet.Auto, _ 
     CallingConvention:=CallingConvention.StdCall)> _ 
Public Overloads Shared Function GetModuleHandle(ByVal sLibName As String) As IntPtr 
End Function 

<DllImport("kernel32.dll", EntryPoint:="FreeLibrary", _ 
    SetLastError:=True, CallingConvention:=CallingConvention.StdCall)> _ 
Public Overloads Shared Function FreeLibrary(ByVal hMod As IntPtr) As Integer 
End Function 

Y a continuación, antes de salir de la aplicación:

Dim hOwcHandle As IntPtr = GetModuleHandle("AcroPDF.dll") 
If Not hOwcHandle.Equals(IntPtr.Zero) Then 
    FreeLibrary(hOwcHandle) 
    Debug.WriteLine("AcroPDF.dll freed") 
End If 

Este procedimiento puede ser modificado por cualquier otro DLL portado mal. Solo espero que no introduzca ningún error nuevo.

+0

¡Esto funcionó para mí! Algunas DLL VB6 no se liberaron antes de la llamada a System.Environment.Exit(). – JRS

+0

Gran solución, funcionó para mí. Gracias – ahoo

+0

¡Muchas gracias! El uso de los métodos GetModuleHandle y FreeLibrary me ayudó a limpiar mis recursos no administrados que no se estaban liberando. – Frinavale

Cuestiones relacionadas