Como puedo depurar un fallo de asignacion de memoria en C++???

Iniciado por kafok, 9 Noviembre 2014, 19:55 PM

0 Miembros y 3 Visitantes están viendo este tema.

kafok

Hola, mi problema es que estoy trabajando en una librería la cual estuve planificando el diseño tiempo. La libreria es una DLL que en principio esta pensada para ser linkeada de forma estatica (el diseño es mas facil y se adecua al sistema de clases que tengo). Bueno pues mi proyecto esta organizado de la siguiente manera, tengo tres proyectos los cuales es la misma libreria implementada de varias formas. El primero es un programa con su main y dentro del proyecto esta la libreria, de esta forma la testeo facilmente. Acto seguido copio el codigo en el proyecto que crea la DLL y la compilo teniendo como resultado una DLL ya testada. Por ultimo en otro proycto linkeado a la DLL hago exactamente las mismas pruebas que en el primer proyecto y asi me aseguro que la DLL funciona como debe.

Para mi este sistema es comodo ya que no tengo que andar con dos proyectos, el que compile la DLL y otro aparte para probarlo, sino que creo el codigo en uno aparte lo testeo y una vez comprobado copio y pego en el proyecto final y los resultados de los test deben ser iguales.

Aqui mi problema, resulta que en el proyecto inicial los test van de maravilla, no hay errores en la clase que estoy testando. En el proyecto que incluya la DLL no se esperan anomalias, ya que el codigo es el mismo, se comprueba que se haya contruido bien la DLL ya que el funcionamiento de las clases ya se a comprobado, pero bueno un copia y pega no esta de mas.

Ahora... llevo con este problema alrededor de un mes investigando y no hayo respuesta. Comprobando los constructores de la unica clase que llevo resulta que si se instancia de forma estatica, es decir, como variable, no da problemas (TODO ESTO EN EL PROYECTO FINAL, EN EL PRIMERO TODO FUNCIONA BIEN), pero cuando hago uso del operador new para llamar a algun constructor de una clase pasa algo rarisimo, hay veces que el programa termina correctamente, pero no crea el objeto (no se ve por pantalla) y otras que la aplicacion crashea, el tipico: Esta aplicacion a dejado de funcionar, de windows. He probado a poner el test en un bloque try, pero no me recoje ninguna excepcion, y lo mas extraño es que no pasa siempre, no siempre crashea, lo que me hace pensar que el codigo esta bien, es mas cuando no se instancia con new todo funciona bien.

¿Como puedo encontrar el error?¿como puedo saber por que Windows cierra la aplicacion asi, es decir, saber cual es la causa?

Probe a crear una libreria estatica con el mismo resultado.....  :-(

PD: no pongo el codigo pues se trata de un proyecto grande con muchisimos archivos y la clase de la que hablo contiene mucho codigo

Eternal Idol

Usa el WinDbg; File>>Open Executable; F5 para arrancar, cuando de la excepcion usa kb ffff para ver la pila (ALT+6 para la ventana), dv parar las variables locales, .etc.
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

kafok

Muchas, gracias, la verdad ando un poco perdido, aunque llevo unos añitos programando nunca me he visto en la necesidad de depurar, simplemente probando a cambiar cosas y observando resultados he sido capaz de solucionar problemas, rara vez me ha echo falta depurar. Bueno, al grano, no se usar WinDbg, aun hay cosas que me faltan por manejar, y sobre todo cosas de tan bajo nivel,  asi que me podrias indicar donde puedo aprender a usar este programa, o como resolver mi problema que no es mas que saber porque crashea la aplicacion

Eternal Idol

El programa tiene una extensa ayuda y sino busca en Google tutoriales; ese problema puede llegar a ser resuelto en 5 minutos (las instrucciones que te deje antes serian suficientes) o en varios dias (puede ser un problema de sincronizacion, un memory leak o vaya uno saber).
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

kafok

Es que cuando depuro no salta la excepcion...  :-(
Deben salir textos por pantalla pero solo salen simbolos extrañisimos cuando depuro. Hice un programa que llamara a un metodo desde un puntero nulo y si salta la excepcion pero en el mio no me salta ningun error.... No se que mas hacer, estoy desesperaisimo yaaa!!

kub0x

#5
Estoy con Eternal, no parece gran cosa...

Ocurre una excepción no controlada, por lo que salta el filtro de excepciones por defecto del programa y por eso no llega a ejecutar tu bloque try-catch. Prueba a depurar bien, obten la stacktrace y ve paso por paso. No te rindas.

Si manejas la WinAPI podrías cambiar el filtro de excepciones no controladas por el tuyo propio usando SetUnhandledExceptionFilter pasándole tu propio callback, obteniendo una estructura del contexto del hilo donde se generó la excepción. Dicha estructura contiene la causa de la excepción, valores de los registros de propósito general y la dirección donde ocurrió la excepción. Para obtener la stacktrace usa la API StackWalk. Con esto me armé un módulo de depuración para que me facilitase el trabajo.

Saludos!

APIs a revisar:

SetUnhandledExceptionFilter -> http://msdn.microsoft.com/es-es/library/windows/desktop/ms680634%28v=vs.85%29.aspx
SymInitialize -> http://msdn.microsoft.com/en-us/library/windows/desktop/ms681351%28v=vs.85%29.aspx
StackWalk -> http://msdn.microsoft.com/en-us/library/windows/desktop/ms680650%28v=vs.85%29.aspx
Viejos siempre viejos,
Ellos tienen el poder,
Y la juventud,
¡En el ataúd! Criaturas Al poder.

Visita mi perfil en ResearchGate


Eternal Idol

#6
Cita de: kafok en 10 Noviembre 2014, 02:39 AM
Es que cuando depuro no salta la excepcion...  :-(
Deben salir textos por pantalla pero solo salen simbolos extrañisimos cuando depuro. Hice un programa que llamara a un metodo desde un puntero nulo y si salta la excepcion pero en el mio no me salta ningun error.... No se que mas hacer, estoy desesperaisimo yaaa!!

Solucion, ejecuta el WinDbg con la linea de comandos -I (loggeado como Administrador desde cmd) para configurarlo como depurador post-mortem, de esta manera se abrira automaticamente el WinDbg en cuanto se produzca la excepcion. Si solo ves simbolos extraños tenes que generar la informacion de depuracion (archivos .pdb), no se que herramientas estaras usando pero normalmente en el IDE se puede configurar facilmente.

Enabling Postmortem Debugging

Specifying a Postmortem Debugger
To set the postmortem debugger to WinDbg, run windbg -I. (The I must be capitalized.) This command will display a success or failure message after it is used. When WinDbg is the postmortem debugger, it will be activated whenever an application crashes.
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

kafok

Cita de: kub0x en 10 Noviembre 2014, 04:42 AM
Estoy con Eternal, no parece gran cosa...
Ya se que sera al final una tonteria... pero es que nunca he tenido que utililar herramientas tan complejas para depurar.

Bueno kub0x he estado toda la tarde trasteando, googleando, leyendo la documentacion de windows... bueno he estado tambien testeando con programas que fallaban a posta y recogiendo las excepciones y bueno este es el codigo que he empleado para recojerlas:

Código (cpp) [Seleccionar]
LONG WINAPI MyUnhandledExceptionFilter(_EXCEPTION_POINTERS *e)
{
    cout << e->ExceptionRecord->ExceptionAddress << endl;
    cout << e->ExceptionRecord->ExceptionCode << endl;
    cout << e->ExceptionRecord->ExceptionFlags << endl;
    cout << e->ExceptionRecord->ExceptionInformation << endl;
    cout << e->ExceptionRecord->NumberParameters << endl;
   
    system("pause");

    return EXCEPTION_EXECUTE_HANDLER;
}


Haber el comando "pause" se debe a que el codigo lo tengo que ejecutar varias veces porque no siempre crashea, es depende como le pille, aunque la mayotia de veces si crashea y para dificultar las cosas cuando se esta depurando no crashea, vamos que mi propio codigo me esta vacilando como quien dice -,-"

Bueno la salida es esta:
Código (dos) [Seleccionar]
0x77340b8f
3221225477
0
0x28f6b0
2
Presione una tecla para continur...


Bueno, la segunda linea es la que he visto interesante, 3221225477 que en hx es 0xC0000005 y segun winbase.h equivale al codigo EXCEPTION_ACCESS_VIOLATION, es decir el mismo codigo que cuando llamo al metodo de un objeto puntero que apunta a NULL. Aun asi he buscado en internet lo referente a este error y no viene nada en ningun lado...

¿Como averiguo que esta pasando?¿Vale ya se que excepcion salta y ahora qué si no se que la provoca?

Eternal Idol

Cita de: kafok en 11 Noviembre 2014, 01:29 AM¿Como averiguo que esta pasando?¿Vale ya se que excepcion salta y ahora qué si no se que la provoca?

Viendo la pila; esto tiene pinta de corrupcion de memoria por lo que comentaste de new y por la direccion que huele a API. Application Verifier puede ayudar mucho a simplificar la investigacion, dependieno del problema de origen es capaz de detectarlo incluso antes de que termine por explotar ...

Cita de: kafok en 11 Noviembre 2014, 01:29 AM
Haber el comando "pause" se debe a que el codigo lo tengo que ejecutar varias veces porque no siempre crashea, es depende como le pille, aunque la mayotia de veces si crashea y para dificultar las cosas cuando se esta depurando no crashea, vamos que mi propio codigo me esta vacilando como quien dice -,-"

En mi anterior mensaje te deje la forma para que, sin tocar tu codigo, se abra automaticamente el depurador (WinDbg) cuando se produzca la excepcion.
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

kub0x

@kafok: si tienes los símbolos de debug (pdb) podrías utilizar SymInitialize y SymFromAddr con StackWalk para recorrer la pila y detectar en que funciones ha ido fallando, es decir, todavía te falta code (pero vas pillando el concepto).

Si quieres resultados rápidos la forma de Eternal Idol es la más recomendable, ya que él te ofrece un mecanismo por el cual filtrar todas las excepciones no controladas mediante windbg.

Una vez en windbg

Cita de: Eternal Idol en  9 Noviembre 2014, 20:20 PM
[..] cuando de la excepcion usa kb ffff para ver la pila (ALT+6 para la ventana), dv parar las variables locales, .etc.

Saludos!
Viejos siempre viejos,
Ellos tienen el poder,
Y la juventud,
¡En el ataúd! Criaturas Al poder.

Visita mi perfil en ResearchGate