¿Cuáles son los patrones de llenado de la memoria de depuración en Visual Studio C++ y Windows?
En Visual Studio, todos hemos tenido "baadf00d", hemos visto "CC" y "CD" al inspeccionar variables en el depurador en C++ durante el tiempo de ejecución.
Por lo que tengo entendido, "CC" está en modo DEBUG solo para indicar cuando una memoria ha sido nueva () o alloc () y unilializada. Mientras que "CD" representa memoria eliminada o liberada. Sólo he visto "baadf00d" en la versión RELEASE (pero puede que me equivoque).
De vez en cuando, nos encontramos en una situación en la que tenemos que abordar pérdidas de memoria, desbordamientos de búfer, etc., y este tipo de información resulta útil.
¿Alguien sería tan amable de señalar cuándo y en qué modos la memoria se configura con patrones de bytes reconocibles para fines de depuración?
Este enlace tiene más información:
https://en.wikipedia.org/wiki/Magic_number_(programming)#Debug_values
* 0xABABABAB: Utilizado por HeapAlloc() de Microsoft para marcar bytes de protección de "tierra de nadie" después de la memoria de montón asignada. * 0xABADCAFE: un inicio con este valor para inicializar toda la memoria libre para detectar punteros erróneos * 0xBAADF00D: Utilizado por LocalAlloc (LMEM_FIXED) de Microsoft para marcar la memoria de montón asignada no inicializada * 0xBADCAB1E: Código de error devuelto al depurador de Microsoft eVC cuando se corta la conexión con el depurador * 0xBEEFCACE: Utilizado por Microsoft .NET como número mágico en archivos de recursos * 0xCCCCCCCC: Utilizado por la biblioteca de tiempo de ejecución de depuración C++ de Microsoft para marcar la memoria de pila no inicializada. * 0xCDCDCDCD: Utilizado por la biblioteca de tiempo de ejecución de depuración C++ de Microsoft para marcar la memoria del montón no inicializada. * 0xDDDDDDDD: Utilizado por el montón de depuración de C++ de Microsoft para marcar la memoria del montón liberada. * 0xDEADDEAD: un código de error de DETENCIÓN de Microsoft Windows que se utiliza cuando el usuario inicia manualmente el bloqueo. * 0xFDFDFDFD: Utilizado por el montón de depuración de C++ de Microsoft para marcar los bytes de protección de "tierra de nadie" antes y después de la memoria del montón asignada. * 0xFEEEFEEE: Utilizado por HeapFree() de Microsoft para marcar la memoria del montón liberada.
En realidad, se agrega bastante información útil a las asignaciones de depuración. Esta tabla es más completa:
http://www.nobugs.org/developer/win32/debug_crt_heap.html#table
Desplazamiento de dirección después de HeapAlloc() Después de malloc() Durante free() Después de HeapFree() Comentarios 0x00320FD8 -40 0x01090009 0x01090009 0x01090009 0x0109005A Información del montón Win32 0x00320FDC -36 0x01090009 0x00180700 0x01090009 0x00180400 Información del montón Win32 0x00320FE0 -32 0xBAADF00D 0x00320798 0xDDDDDDDD 0x00320448 Ptr al siguiente bloque de montón CRT (asignado anteriormente en el tiempo) 0x00320FE4 -28 0xBAADF00D 0x00000000 0xDDDDDDDD 0x00320448 Ptr al bloque de montón CRT anterior (asignado más adelante en el tiempo) 0x00320FE8 -24 0xBAADF00D 0x00000000 0xDDDDDDDD 0xFEEEFEEE Nombre de archivo de la llamada malloc() 0x00320FEC -20 0xBAADF00D 0x00000000 0xDDDDDDDD 0xFEEEFEEE Número de línea de llamada malloc() 0x00320FF0 -16 0xBAADF00D 0x00000008 0xDDDDDDDD 0xFEEEFEEE Número de bytes para malloc() 0x00320FF4 -12 0xBAADF00D 0x00000001 0xDDDDDDDD 0xFEEEFEEE Tipo (0=Liberado, 1=Normal, 2=uso CRT, etc.) 0x00320FF8 -8 0xBAADF00D 0x00000031 0xDDDDDDDD 0xFEEEFEEE Solicitud #, aumenta desde 0 0x00320FFC -4 0xBAADF00D 0xFDFDFDFD 0xDDDDDDDD 0xFEEEFEEE Tierra de nadie 0x00321000 +0 0xBAADF00D 0xCDCDCDCD 0xDDDDDDDD 0xFEEEFEEE Los 8 bytes que querías 0x00321004 +4 0xBAADF00D 0xCDCDCDCD 0xDDDDDDDD 0xFEEEFEEE Los 8 bytes que querías 0x00321008 +8 0xBAADF00D 0xFDFDFDFD 0xDDDDDDDD 0xFEEEFEEE Tierra de nadie 0x0032100C +12 0xBAADF00D 0xBAADF00D 0xDDDDDDDD 0xFEEEFEEE Las asignaciones de montón de Win32 se redondean a 16 bytes 0x00321010 +16 0xABABABAB 0xABABABAB 0xABABABAB 0xFEEEFEEE Contabilidad del montón Win32 0x00321014 +20 0xABABABAB 0xABABABAB 0xABABABAB 0xFEEEFEEE Contabilidad del montón Win32 0x00321018 +24 0x00000010 0x00000010 0x00000010 0xFEEEFEEE Contabilidad del montón Win32 0x0032101C +28 0x00000000 0x00000000 0x00000000 0xFEEEFEEE Contabilidad del montón Win32 0x00321020 +32 0x00090051 0x00090051 0x00090051 0xFEEEFEEE Contabilidad del montón Win32 0x00321024 +36 0xFEEE0400 0xFEEE0400 0xFEEE0400 0xFEEEFEEE Contabilidad del montón Win32 0x00321028 +40 0x00320400 0x00320400 0x00320400 0xFEEEFEEE Contabilidad del montón Win32 0x0032102C +44 0x00320400 0x00320400 0x00320400 0xFEEEFEEE Contabilidad del montón Win32
En cuanto a y en particular, se trata de reliquias de la instrucción del procesador Intel 8088/80860xCC
de 0xCD
la década de 1980 . 0xCC
Es un caso especial del código de operación de interrupción de software . La versión especial de un solo byte permite que un programa genere la interrupción 3 .INT
0xCD
0xCC
Aunque los números de interrupción del software son, en principio, arbitrarios, INT 3
tradicionalmente se utilizaban para la función de interrupción o punto de interrupción del depurador , una convención que se mantiene hasta el día de hoy. Cada vez que se inicia un depurador, instala un controlador de interrupciones de modo INT 3
que cuando se ejecute ese código de operación, se active el depurador. Por lo general, pausará la programación que se está ejecutando actualmente y mostrará un mensaje interactivo.
Normalmente, el código de operación x86 INT
ocupa dos bytes: 0xCD
seguido del número de interrupción deseado del 0 al 255. Entonces, aunque podría emitir 0xCD 0x03
para INT 3
, Intel decidió agregar una versión especial, 0xCC
sin bytes adicionales, porque un código de operación debe tener solo un byte para funcionar como un 'byte de relleno' confiable para la memoria no utilizada.
El punto aquí es permitir una recuperación elegante si el procesador salta por error a una memoria que no contiene ninguna instrucción prevista . Las instrucciones de varios bytes no son adecuadas para este propósito, ya que un salto erróneo podría aterrizar en cualquier posible desplazamiento de bytes donde tendría que continuar con un flujo de instrucciones formado correctamente.
Obviamente, los códigos de operación de un byte funcionan de manera trivial para esto, pero también puede haber excepciones extravagantes: por ejemplo, considerando la secuencia de llenado 0xCDCDCDCD
(también mencionada en esta página), podemos ver que es bastante confiable ya que no importa dónde aterrice el puntero de instrucción ( excepto quizás el último byte llenado), la CPU puede reanudar la ejecución de una instrucción x86 válida de dos bytesCD CD
, en este caso para generar la interrupción de software 205 (0xCD).
Lo que es aún más extraño, mientras que CD CC CD CC
es 100% interpretable (dando o INT 3
o INT 204
), la secuencia CC CD CC CD
es menos confiable, solo el 75% como se muestra, pero generalmente el 99,99% cuando se repite como un relleno de memoria de tamaño int.
Referencia del macroensamblador , 1987