Pregunta

Estoy tratando de añadir mejoras al programa de un VC de 4 años ++ 6.0. La versión de depuración se extiende desde la línea de comandos, pero no en el depurador: se estrella con una violación de acceso al interior de printf (). Si me salto el printf, a continuación, se bloquea en malloc () (llamada desde dentro de fopen ()) y no puedo pasar por alto eso.

Esto significa que no se puede ejecutar en el depurador y tienen que depender de las sentencias printf viejos para ver lo que está pasando. Obviamente, esto hace que sea mucho más difícil.

Cualquier idea de por qué printf () y malloc () fallará cuando se ejecuta en el depurador VC ++? No soy bueno en estas cosas de bajo nivel!

Esta es la pila de llamadas después de la violación de acceso:

_heap_alloc_dbg(unsigned int 24, int 2, const char * 0x0046b3d8 `string', int 225) line 394 + 8 bytes
_nh_malloc_dbg(unsigned int 24, int 0, int 2, const char * 0x0046b3d8 `string', int 225) line 242 + 21 bytes
_malloc_dbg(unsigned int 24, int 2, const char * 0x0046b3d8 `string', int 225) line 163 + 27 bytes
_lock(int 2) line 225 + 19 bytes
_getstream() line 55 + 7 bytes
_fsopen(const char * 0x00468000 `string', const char * 0x00466280 `string', int 64) line 61 + 5 bytes
fopen(const char * 0x00468000 `string', const char * 0x00466280 `string') line 104 + 15 bytes
open_new_log(const char * 0x00468000 `string') line 66 + 14 bytes
log_open(const char * 0x00468000 `string', int 0) line 106 + 9 bytes
Xlog_open(const char * 0x00468000 `string', int 0) line 51 + 13 bytes
service_start(unsigned long 1, char * * 0x009a0e50) line 3152 + 12 bytes
service_init2(char * 0x00471fcc char * NTPROGRAM, char * 0x004723c4 char * NTSERVICE, char * 0x00466540 `string', unsigned long 1, char * * 0x009a0e50) line 508 + 13 bytes
service_init(char * 0x00471fcc char * NTPROGRAM, char * 0x004723c4 char * NTSERVICE, unsigned long 2, char * * 0x009a0e50) line 548
main(unsigned long 2, char * * 0x009a0e50) line 3131
mainCRTStartup() line 206 + 25 bytes
KERNEL32! 7c817067()

Esta es la depuración Desensamblaje hasta la operación que falla:

0041EA7E   jmp         _heap_alloc_dbg+2B3h (0041eb23)
0041EA83   mov         edx,dword ptr [_lTotalAlloc (004b4294)]
0041EA89   add         edx,dword ptr [nSize]
0041EA8C   mov         dword ptr [_lTotalAlloc (004b4294)],edx
0041EA92   mov         eax,[_lCurAlloc (004b429c)]
0041EA97   add         eax,dword ptr [nSize]
0041EA9A   mov         [_lCurAlloc (004b429c)],eax
0041EA9F   mov         ecx,dword ptr [_lCurAlloc (004b429c)]
0041EAA5   cmp         ecx,dword ptr [_lMaxAlloc (004b42a0)]
0041EAAB   jbe         _heap_alloc_dbg+249h (0041eab9)
0041EAAD   mov         edx,dword ptr [_lCurAlloc (004b429c)]
0041EAB3   mov         dword ptr [_lMaxAlloc (004b42a0)],edx
0041EAB9   cmp         dword ptr [_pFirstBlock (004b4298)],0
0041EAC0   je          _heap_alloc_dbg+25Fh (0041eacf)
0041EAC2   mov         eax,[_pFirstBlock (004b4298)]
0041EAC7   mov         ecx,dword ptr [pHead]
0041EACA   mov         dword ptr [eax+4],ecx

Aquí es nuestra fuente para que llama fopen () y falla en malloc ()

FILE *open_new_log( const char *logfile )
{
    FILE *fp;
    int retry = 0;

    while( ( fp = fopen( logfile, "w" ) ) == NULL && ++retry < 300 )
        Sleep( 1000 );

    return( fp );
}

El error que consigo es

Unhandled exception inPISCOOP.exe: 0xC00000005: Access Violation

Saludos,

--- Alistair.

¿Fue útil?

Solución

Puede utilizar _CrtSetDbgFlag() para permitir un grupo de técnicas útiles montón de depuración. Hay una serie de otros funciones CRT de depuración disponibles que debería ayudar a localizar dónde está su problema.

Otros consejos

Cuando se ejecuta desde el depurador, se utiliza un montón diferente; esto se conoce como el montón de depuración . Esto tiene un comportamiento diferente del montón utilizado fuera del depurador, y está ahí para ayudar a detectar los problemas como éste.

Tenga en cuenta que el Win32 "montón de depuración" es distinta de la VC ++ "montón de depuración"; ambos están destinados a hacer más o menos lo mismo, sin embargo. Ver este artículo que describe la diferencia de comportamiento cuando se ejecuta la aplicación bajo el depurador.

En este caso, es probable que haya dañado el montón antes de llamar a esta función, ya sea por escrito fuera de la final o desactivar el inicio de un bloque del montón.

La forma más fácil de enfoques (siempre que su aplicación no utiliza la memoria demasiado extensivamente) es permitir comprobación de pila de página completa (que va a colocar la llamada página de protección después de la página de memoria que su asignación se proporciona a partir, lo que, a su vez, identificar el lugar exacto en el código donde la corrupción se lleva a cabo).

Dado que se dispone de herramientas de depuración de Windows práctico, ejecute el siguiente comando para configurar gflags montón de página completa:

gflags[.exe] /p /enable yourapp.exe /full

Nota, debe proporcionar el nombre del ejecutable solo (es decir, sin prefijo de ruta!)
A continuación, sólo ejecutar el programa bajo el depurador - se romperá con el primer intento de dañar la pila. La diferencia aquí es que corrupciones montón son defectos que se manifiestan más tarde, cuando una (posiblemente) operación de lixiviación válido es en efecto principalmente retraso.

Tenga en cuenta, también:

gflags[.exe] /p /enable yourapp.exe /full /backwards

Además se coloque una página de protección antes de su asignación.

Correr con modificador / p solos, aparecerán las opciones de pila de página actualmente en vigor.

Es posible que tenga un Desbordamiento de la memoria. Su aplicación puede haber dañado el montón antes open_new_log() se llama.

Sospecho jmattias tiene razón. La causa raíz del problema es probable que en algún otro lugar en el que está fallando.

Muchas cosas pueden causar daños en la pila.

  • escritura más allá del final (o al principio) del bloque de memoria que se ha asignado.
  • liberar un puntero dos veces, o liberar un puntero que no se ha asignado.
  • multithreading su programa y que conecta con el de un único subproceso (no seguro para subprocesos) RTL.
  • asignación de memoria de un montón y liberándola en otro montón.
  • etc., Etc.,

Dado que está utilizando Visual C ++, puede utilizar la función de _CrtSetDbgFlag () del montón de depuración para encender la comprobación de errores. Puedes configurarlo para comprobar la integridad de la pila en cada llamada a malloc o libre. Eso va a funcionar muy lentamente, pero se debe señalar que el fallo es para usted.

Búsqueda de _CrtSetDbgFlag en la documentación del compilador.

Tengo la sospecha de que hay una DLL compilada con una versión diferente del tiempo de ejecución de C ++ que el resto de la aplicación. Esto dará lugar a menudo en "memoria en la dirección XXX no se puede 'leer' / 'escritas'" violaciónes.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top