c++ debugging winapi crash gdi

c++ - Heisenbug: el programa WinApi falla en algunas computadoras



debugging crash (11)

1) El bloqueo solo ocurre en la versión de lanzamiento.

Por lo general, eso es señal de que está confiando en un comportamiento que no está garantizado, pero sucede que es cierto en la compilación de depuración. Por ejemplo, si olvida inicializar sus variables o acceder a una matriz fuera de límites. Asegúrese de haber activado todas las comprobaciones del compilador (/ RTCsuc). También verifique cosas como confiar en el orden de evaluación de los parámetros de la función (que no está garantizado).

2) El bloqueo desaparece tan pronto como elimino todas las cosas relacionadas con GDI.

Tal vez eso es una pista de que estás haciendo algo mal con las cosas relacionadas con GDI. ¿Estás usando HANDLEs después de haber sido liberados, por ejemplo?

¡Por favor ayuda! Estoy realmente en mi ingenio. Mi programa es un pequeño administrador de notas personales (google para "cintas de video"). En algunas computadoras (y, por supuesto, no poseo ninguna), se bloquea con una excepción no controlada justo después del inicio. No se puede decir nada especial acerca de estas computadoras, excepto que tienden a tener CPU AMD.

Entorno: Windows XP, Visual C ++ 2005/2008, WinApi sin formato.

Aquí está lo que es cierto acerca de este "Heisenbug":

1) El bloqueo solo ocurre en la versión de lanzamiento.

2) El bloqueo desaparece tan pronto como elimino todas las cosas relacionadas con GDI.

3) BoundChecker no tiene quejas.

4) ¡Escribir un registro muestra que el bloqueo ocurre en una declaración de una variable int local! ¿Cómo es posible? ¿Corrupción de memoria?

¡Cualquier idea sería muy apreciada!

ACTUALIZACIÓN: Logré que la aplicación se depurara en una PC "defectuosa". Los resultados:

"Excepción no controlada en 0x0044a26a en CintaNotes.exe: 0xC000001D: instrucción ilegal".

y el código se rompe en

0044A26A cvtsi2sd xmm1, dword ptr [esp + 14h]

Parece que el problema estaba en la opción del compilador "Generación de código / habilitar conjunto de instrucciones mejorado". Se configuró en "/ arch: SSE2" y se bloqueaba en las máquinas que no admitían SSE2. Establecí esta opción en "No establecido" y el error desapareció. ¡Uf!

¡Muchas gracias a todos por la ayuda!


4) Escribir un registro muestra que el bloqueo ocurre en una declaración de una variable int local. ¿cómo es posible? ¿Corrupción de memoria?

¿Cuál es el código subyacente en el ejecutable / ensamblado? La declaración de int no es código en absoluto, y como tal no puede bloquearse. ¿Inicializas la int de alguna manera?

Para ver el código donde ocurrió el bloqueo, debe realizar lo que se denomina análisis post mortem.

Informes de errores de Windows

Si desea analizar el bloqueo, debería obtener un volcado de emergencia. Una opción para esto es registrarse para Windows Error Reporting: requiere algo de dinero (necesita una identificación de firma de código digital) y algún formulario de llenado. Para obtener más información, visite https://winqual.microsoft.com/ .

Obtenga el volcado de emergencia previsto para WER directamente del cliente

Otra opción es ponerse en contacto con un usuario que está experimentando el bloqueo y obtener un volcado de memoria directamente para él. El usuario puede hacer esto cuando hace clic en los detalles técnicos antes de enviar el bloqueo a Microsoft: la ubicación del archivo de volcado de emergencia se puede verificar allí.

Su propio minivolcado

Otra opción es registrar su propio manejador de excepciones, manejar la excepción y escribir un minivolcado en cualquier lugar que desee. Puede encontrar una descripción detallada en Code Project Post-Mortem Debugging Your Application con Minidumps y el artículo de Visual Studio .NET .


4) Escribir un registro muestra que el bloqueo ocurre en una declaración de una variable int local. ¿Cómo podría ser eso? Corrupción de la memoria

He encontrado la causa de numerosos "choques extraños" para desreferenciar de this dentro de una función miembro de dicho objeto.


"4) ¡Escribir un registro muestra que el bloqueo ocurre en una declaración de una variable int local! ¿Cómo podría ser eso? ¿Daño en la memoria?"

Esto podría ser una señal de que el hardware es de hecho defectuoso o está siendo empujado demasiado. Averigüe si han overclocked su computadora.


¿Entonces no se cuelga cuando la configuración es DEBUG Configuration? Hay muchas cosas diferentes a una configuración de LIBERACIÓN: 1.) Inicialización de globales 2.) Código de máquina real generado, etc.

El primer paso es averiguar cuáles son las configuraciones exactas para cada parámetro en el modo RELEASE en comparación con el modo DEBUG.

-ANUNCIO


¿Qué dice el choque? Violación de acceso? Excepción? Esa sería la pista más para resolver esto con

Asegúrese de no tener corrupciones de memoria anteriores con PageHep.exe

Asegúrese de que no tiene desbordamiento de pila (CBig array [1000000])

Asegúrese de no tener memoria no inicializada.

Además, puede ejecutar la versión de lanzamiento también dentro del depurador, una vez que genere los símbolos de depuración (no es lo mismo que crear la versión de depuración) para el proceso. Examine y vea si está recibiendo advertencias en la ventana de seguimiento del depurador.


Descargue las herramientas de depuración para el paquete de Windows . Establezca las rutas de símbolos correctamente, luego ejecute su aplicación bajo WinDbg. En algún momento, se romperá con una Infracción de acceso. Entonces debería ejecutar el comando "! Analyze -v", que es bastante inteligente y debería darle una pista sobre lo que está yendo mal.


La mayoría de los errores heisenbugs / solo de liberación se deben al flujo de control que depende de las lecturas de la memoria no inicializada / punteros obsoletos / finales de los almacenamientos intermedios, o condiciones de carrera, o ambas.

Intente anular sus asignaturas para que pongan a cero la memoria al asignar. ¿El problema desaparece (o se vuelve más reproducible?)

¡Escribir un registro muestra que el bloqueo ocurre en una declaración de una variable int local! ¿Cómo es posible? ¿Corrupción de memoria?

¡Desbordamiento de pila! ;)


Cuando obtengo este tipo de cosas, intento ejecutar el código a través de gimpels PC-Lint (análisis de código estático), ya que comprueba diferentes clases de errores en BoundsChecker. Si está utilizando Boundschecker, active las opciones de envenenamiento de memoria.

Mencionas CPU AMD. ¿Ha investigado si existe una versión y / o configuración similar de tarjeta gráfica / controlador en las máquinas que fallan? ¿Siempre se cuelga en estas máquinas o solo ocasionalmente? Tal vez ejecute la herramienta de Información del sistema en estas máquinas y vea qué tienen en común,


Me suena a corrupción de pila. Mi herramienta favorita para rastrearlos es IDA Pro . Por supuesto, no tienes ese acceso a la máquina del usuario.

Algunas fichas de memoria tienen dificultades para atrapar la corrupción de la pila (si es así). La forma más segura de obtener esos creo que es el análisis del tiempo de ejecución.

Esto también puede deberse a daños en una ruta de excepción, incluso si se manejó la excepción. ¿Se ha activado la depuración con ''atrapar excepciones de primera oportunidad''? Deberías hacerlo todo el tiempo que puedas. Se vuelve molesto después de un tiempo en muchos casos.

¿Puedes enviarles a esos usuarios una versión comprobada de tu aplicación? Echa un vistazo a Minidump Handle that exception y escribe un volcado. Luego use WinDbg para depurar en su extremo.

Otro método es escribir registros muy detallados. Cree una opción "Registrar cada acción individual" y solicite al usuario que la active y la envíe también a usted. Volcar la memoria a los registros. Consulte ''_CrtDbgReport ()'' en MSDN.

¡Buena suerte!

EDITAR:

Respondiendo a tu comentario: un error en una declaración de variable local no me sorprende. He visto esto mucho. Por lo general, se debe a una pila corrupta.

Algunas variables en la pila pueden estar ejecutándose por encima de sus límites, por ejemplo. Todo el infierno se desata después de eso. A continuación, las declaraciones de variables de pila arrojan errores de memoria aleatoria, las tablas virtuales se corrompen, etc.

Cada vez que los he visto por un período prolongado de tiempo, he tenido que ir a IDA Pro. La depuración detallada del desensamblaje en tiempo de ejecución es lo único que sé que realmente los obtiene de manera confiable.

Muchos desarrolladores usan WinDbg para este tipo de análisis. Es por eso que también sugerí Minidump.


Pruebe Rational (IBM) PurifyPlus. Captura muchos errores que BoundsChecker no.