sábado, julio 10, 2010

c++ casque valgrind

Programa C++ con warper en Qt

El programa se ejecuta sin problemas, es un programa sencillo

Pero muy de vez en cuando, el programa explota

No es fácil reproducirlo y generar ese casque

Después de bastante tiempo de observación, veo que explota después de dejarlo inactivo duranto un periodo de tiempo. Curioso

Reproduzco el error haciendo un volcado de memoria con la tabla de símbolos.

El resultado es incoherente, si ningún sentido.

Así que le paso valgrind y...


vaya, parece que hay unos cuantos errores y uno de ellos es AL INICIAR el programa

Es un error de punteros (acceso a una memoria borrada)

La librería que estoy preparado, intenta que estas cosas no puedan pasar fácilmente

* Captura y gestiona el error de división por cero de enteros
* Utiliza siempre countptr. No tienen aritmética de punteros, no se puede pedir la dirección del puntero si este no es válido...
* Contenedores con verificación de límites y validad de iteradores
* ...

Aún así hay un error en el arranque

El problema viene por un sutil cambio en el orden de un par de señales

Una señal indica el cambio de estado y la otra gestiona la acción a realizar en este cambio

¿Se debe cambiar el estado y luego generar la acción? ¿o al revés?

Supongamos que generamos la acción primero, y como consecuencia de esa acción, se genera una petición a la máquina de estados. SE HARÁ SOBRE UN ESTADO INCORRECTO (caducado, obsoleto)

Entonces, tenemos que cambiar el estado primero y luego generar la acción

Lo malo, es que al cambiar el estado, sale de ámbito el estado anterior MIENTRAS SIGUE EJECUTÁNDOSE código de dicho estado

La solución es muy sencilla, pero esa no es la cuestión. La cuestión es porqué se pueden cometer este tipo de errores sin darse cuenta, siendo estos errores tan difíciles de localizar (si no fuera por valgrind)
Y sobre todo, la cuestión es qué se puede hacer para evitarlo

Un consejo frecuente con los eventos o los signal-slot, es que se llamen al final del método

No siempre es posible

Creo que tener un signal-slot asíncrono, sería de gran ayuda para evitar estas situaciones y simplificar otras

Un signal-slot asíncrono podría trabajar fácilmente entre hebras, aunque eso no me interesa en este momento

En un sistema no paralelo, sería mejor que el sistema de signal-slot asíncronos (funcionarían de forma muy parecida a mensajes) despachara en el mismo orden en que se producen

Un sistema de signal-slot asíncrono con tipado fuerte, parece que sería caro
Con tipado débil, sería una implementación mucho más sencilla, menos memoria para datos y programa, pero sin verificación de tipos en compilación y más lento en ejecución


Volviendo al problema, un error en punteros al iniciar el programa, genera que este explote pasado bastante tiempo. Además, es necesario dejar el programa inactivo un buen rato y hacer otras cosas (lo que generará reordenación de la memoria del proceso por parte del sistema operativo)
Sin valgrind, este error sería imposible de localizar y corregir (sus efectos están demasiado lejos del punto donde se produce un error

No hay comentarios: