En Visual Studio C ++, ¿cuáles son las representaciones de asignación de memoria?

216

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 entiendo, "CC" está en modo DEPURACIÓN solo para indicar cuando una memoria ha sido nueva () o alloc () y unitilializada. Mientras que "CD" representa la memoria eliminada o liberada. Solo he visto "baadf00d" en la versión RELEASE (pero puedo estar equivocado).

De vez en cuando, nos encontramos en una situación de tackeo de pérdidas de memoria, desbordamientos de búfer, etc. y este tipo de información es útil.

¿Alguien sería tan amable de señalar cuándo y en qué modos la memoria está configurada en patrones de bytes reconocibles para fines de depuración?

HidekiAI
fuente
@ Lưu Vĩnh Phúc: No es el sistema operativo, es el depurador. La "D" (como en 0xCD y 0xDD) es para Debug (es decir, malloc_dbg es lo que se llama a través de malloc como se explica en msdn.microsoft.com/en-us/library/aa270812(v=vs.60).aspx ). Creo que también agrega cercas / publicaciones alrededor de los montones para rastrear desbordamientos de búfer. Es bastante útil detectar problemas cuando tiene un error de doble eliminación o de liberación múltiple (o incluso una posible llamada de eliminación en lugar de eliminar []) y punteros colgantes que se han eliminado y cuando inspecciona los datos, es "0xDD" (o cuando el montón no inicializado muestra 0xCD)
HidekiAI
No dije que es el sistema operativo. Es el otro autor de la pregunta que escribió el título incorrectamente
phuclv

Respuestas:

317

Este enlace tiene más información:

http://en.wikipedia.org/wiki/Magic_number_(programming)

* 0xABABABAB: utilizado por HeapAlloc () de Microsoft para marcar bytes de protección "tierra de nadie" después de la memoria de montón asignada
* 0xABADCAFE: un inicio a este valor para inicializar toda la memoria libre para atrapar punteros errantes
* 0xBAADF00D: utilizado por LocalAlloc de Microsoft (LMEM_FIXED) para marcar la memoria de montón asignada no inicializada
* 0xBADCAB1E: Código de error devuelto al depurador eVC de Microsoft cuando se corta la conexión al depurador
* 0xBEEFCACE: utilizado por Microsoft .NET como un número mágico en los 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 de montón no inicializada
* 0xDDDDDDDD: utilizado por el montón de depuración C ++ de Microsoft para marcar la memoria de montón liberada
* 0xDEADDEAD: un código de error de DETENCIÓN de Microsoft Windows utilizado cuando el usuario inicia manualmente el bloqueo.
* 0xFDFDFDFD: utilizado por el montón de depuración C ++ de Microsoft para marcar los bytes de guarda "tierra de nadie" antes y después de la memoria de montón asignada
* 0xFEEEFEEE: utilizado por HeapFree () de Microsoft para marcar la memoria de montón liberada
Mark Ingram
fuente
19
Aquí, veo BAADF00D(mala comida), BEEFCACE(pastel de carne), BAADCAB1E(cable malo), BADCAFE(café malo) y DEADDEAD(muerto muerto). ¿Es esto intencional?
Anderson Green
38
@AndersonGreen Por supuesto que es intencional. Se llama hexspeak .
28
Solíamos usar C0CAC01A cuando hacíamos programación de bajo nivel (núcleo del sistema operativo) en los días ...;)
Según Lundberg,
2
0xDEADBEEF, 0xC0EDBABEtambién clásicos incluso si no caen en la lengua vernácula de la EM
J. Paulding
3
Como fanático de Paul McCartney, soy aficionadoBEA71E5
BlueRaja - Danny Pflughoeft
111

En realidad, hay bastante información útil agregada a las asignaciones de depuración. Esta tabla es más completa:

http://www.nobugs.org/developer/win32/debug_crt_heap.html#table

Dirección Offset Después de HeapAlloc () Después de malloc () Durante libre () 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 antes en el tiempo)
0x00320FE4 -28 0xBAADF00D 0x00000000 0xDDDDDDDD 0x00320448 Ptr al bloque de montón CRT anterior (asignado más tarde)
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 a malloc ()
0x00320FF4 -12 0xBAADF00D 0x00000001 0xDDDDDDDD 0xFEEEFEEE Tipo (0 = liberado, 1 = normal, 2 = uso de CRT, etc.)
0x00320FF8 -8 0xBAADF00D 0x00000031 0xDDDDDDDD 0xFEEEFEEE Solicitud #, aumenta de 0
0x00320FFC -4 0xBAADF00D 0xFDFDFDFD 0xDDDDDDDD 0xFEEEFEEE Sin tierra del hombre
0x00321000 +0 0xBAADF00D 0xCDCDCDCD 0xDDDDDDDD 0xFEEEFEEE Los 8 bytes que quería
0x00321004 +4 0xBAADF00D 0xCDCDCDCD 0xDDDDDDDD 0xFEEEFEEE Los 8 bytes que quería
0x00321008 +8 0xBAADF00D 0xFDFDFDFD 0xDDDDDDDD 0xFEEEFEEE Sin tierra del hombre
0x0032100C +12 0xBAADF00D 0xBAADF00D 0xDDDDDDDD 0xFEEEFEEE Las asignaciones del montón Win32 se redondean a 16 bytes
0x00321010 +16 0xABABABAB 0xABABABAB 0xABABABAB 0xFEEEFEEE Contabilidad del montón Win32
0x00321014 +20 0xABABABAB 0xABABABAB 0xABABABAB 0xFEEEFEEE Win32 Heap bookkeeping
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 Win32 heap contabilidad
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
John Dibling
fuente
5

Con respecto 0xCCy 0xCD, en particular, estos son reliquias de la Intel 8088 / 8086 volver conjunto de instrucciones del procesador en la década de 1980. 0xCCes 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 interrupción 3 .INT 0xCD0xCC

Aunque los números de interrupción de software son, en principio, arbitrarios, INT 3se usaban tradicionalmente para la función de interrupción o punto de interrupción del depurador , una convención que se mantiene hasta nuestros días. Cada vez que se inicia un depurador, instala un controlador de interrupciones para que, cuando se ejecute ese código de operación, se active el depurador. Por lo general, pausará la programación actualmente en ejecución y mostrará un mensaje interactivo.INT 3

Normalmente, el INTcódigo de operación x86 tiene dos bytes: 0xCDseguido del número de interrupción deseado de 0-255. Ahora si bien se puede emitir 0xCD 0x03para INT 3, Intel decidió añadir un especial version-- 0xCCsin byte adicional - porque un código de operación debe ser solamente un byte con el fin de funcionar como un fiable 'relleno de bytes' para la memoria no utilizada.

El punto aquí es permitir una recuperación elegante si el procesador salta por error a la memoria que no contiene las instrucciones previstas . 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 correctamente formado.

Obviamente, los códigos de operación de un byte funcionan trivialmente para esto, pero también puede haber excepciones extrañas: por ejemplo, considerando la secuencia de relleno 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 válida x86 de dos bytesCD CD , en este caso para generar la interrupción de software 205 (0xCD).

Aún más extraño, mientras que CD CC CD CCes 100% interpretable, dando cualquiera INT 3o INT 204- la secuencia CC CD CC CDes 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.

página del manual del juego de instrucciones 8088/8086 contemporáneo que muestra instrucciones INT
Referencia de ensamblador macro , 1987

Glenn Slayden
fuente
Wow, no me di cuenta (conecte los dos) 0xCC era INT3. Eso tiene sentido (es decir, no por coincidencia). Solía ​​inyectar "NOP + INT3" en lugares donde hay JMP para inspeccionar registros antes de que saltara en algunas ocasiones (mucho antes). Gracias por esta idea, misterio resuelto!
HidekiAI
¿Para qué fue NOP? ¿No sería suficiente ingresar un solo 0xCCbyte con el ebcomando (ingresar bytes)?
Glenn Slayden
Solo un hábito, en ese entonces, algún código leería dos bytes e intentaría usarlo como tabla de salto, o en algunos casos, cuando enumere el código de ensamblaje, al agregar NOP, no se mostrará como '???' o algo (más legible) al desmontar; en general, por múltiples razones, simplemente se convirtió en un hábito inyectar un NOP antes o después del BRK; Oh, en algunos casos, algunas aplicaciones podrían tratar de hacer la suma de comprobación del bloque de direcciones, así que me gustaría equilibrar la JMP $ XYZW con INT3 + [algunos-hex] sonrisa
HidekiAI