No Visual Studio C ++, quais são as representações de alocação de memória?

216

No Visual Studio, todos nós já tivemos "baadf00d", vimos "CC" e "CD" ao inspecionar variáveis ​​no depurador em C ++ durante o tempo de execução.

Pelo que entendi, "CC" está no modo DEBUG apenas para indicar quando uma memória é nova () ou alocada () e unitilializada. Enquanto "CD" representa a memória excluída ou liberada. Eu só vi "baadf00d" na versão RELEASE (mas posso estar errado).

De vez em quando, nos deparamos com uma situação de vazamento de memória, excesso de buffer etc., e esse tipo de informação é útil.

Alguém teria a gentileza de apontar quando e em que modos a memória está configurada para padrões de bytes reconhecíveis para fins de depuração?

HidekiAI
fonte
@ Lĩu Vĩnh Phúc: Não é o sistema operacional, é o depurador. O "D" (como em 0xCD e 0xDD) é para depuração (ou seja, malloc_dbg é o que é chamado via malloc, conforme explicado em msdn.microsoft.com/en-us/library/aa270812(v=vs.60).aspx ). Acredito que ele também adicione cercas / postes em torno dos montões para rastrear excedentes de buffer. É bastante útil detectar problemas quando você tem um bug de exclusão dupla ou múltipla livre (ou até possível chamada de exclusão em vez de excluir []) e ponteiros pendentes que foram descartados e quando você inspeciona os dados, é "0xDD" (ou quando as mostras de pilha não inicializada 0xCD)
HidekiAI
Eu não disse que é o sistema operacional. É o outro autor da questão que escreveu o título incorretamente
phuclv

Respostas:

317

Este link tem mais informações:

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

* 0xABABABAB: Usado pelo HeapAlloc () da Microsoft para marcar bytes de guarda "terra de ninguém" após a memória de pilha alocada
* 0xABADCAFE: Uma inicialização desse valor para inicializar toda a memória livre para capturar ponteiros errados
* 0xBAADF00D: Usado pelo LocalAlloc da Microsoft (LMEM_FIXED) para marcar a memória heap alocada não inicializada
* 0xBADCAB1E: Código de erro retornado ao depurador do Microsoft eVC quando a conexão é cortada no depurador
* 0xBEEFCACE: usado pelo Microsoft .NET como um número mágico nos arquivos de recursos
* 0xCCCCCCCC: usado pela biblioteca de tempo de execução de depuração C ++ da Microsoft para marcar a memória de pilha não inicializada
* 0xCDCDCDCD: usado pela biblioteca de tempo de execução de depuração C ++ da Microsoft para marcar a memória heap não inicializada
* 0xDDDDDDDD: Usado pelo heap de depuração C ++ da Microsoft para marcar a memória heap liberada
* 0xDEADDEAD: Um código de erro de interrupção do Microsoft Windows usado quando o usuário inicia manualmente a falha.
* 0xFDFDFDFD: Usado pelo heap de depuração em C ++ da Microsoft para marcar os bytes de proteção "terra de ninguém" antes e depois da memória heap alocada
* 0xFEEEFEEE: Usado pelo HeapFree () da Microsoft para marcar a memória heap liberada
Mark Ingram
fonte
19
Aqui, vejo BAADF00D(comida ruim), BEEFCACE(bolo de carne), BAADCAB1E(cabo ruim), BADCAFE(café ruim) e DEADDEAD(morto morto). Isso é intencional?
Anderson Green
38
@AndersonGreen Claro que é intencional. Chama-se hexspeak .
28
Nós costumávamos usar C0CAC01A quando fizemos alguns (kernel do sistema operacional) de baixo nível de volta nos dias de programação ...;)
Per Lundberg
2
0xDEADBEEF, 0xC0EDBABETambém clássicos mesmo se eles não se enquadram em vernáculo do MS
J. Paulding
3
Como fã de Paul McCartney, gosto deBEA71E5
BlueRaja - Danny Pflughoeft 6/15
111

Na verdade, existem algumas informações úteis adicionadas às alocações de depuração. Esta tabela está mais completa:

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

Deslocamento de endereço Após HeapAlloc () Após malloc () Durante grátis () Após HeapFree () Comentários
0x00320FD8 -40 0x01090009 0x01090009 0x01090009 0x0109005A informações de heap do Win32
0x00320FDC -36 0x01090009 0x00180700 0x01090009 0x00180400 informações de heap do Win32
0x00320FE0 -32 0xBAADF00D 0x00320798 0xDDDDDDDD 0x00320448 Ptr para o próximo bloco de heap CRT (alocado anteriormente)
0x00320FE4 -28 0xBAADF00D 0x00000000 0xDDDDDDDD 0x00320448 PTR para bloco de heap CRT anterior (alocado mais tarde)
0x00320FE8 -24 0xBAADF00D 0x00000000 0xDDDDDDDD 0xFEEEFEEE Nome do arquivo da chamada malloc ()
0x00320FEC -20 0xBAADF00D 0x00000000 0xDDDDDDDD 0xFEEEFEEE Número da linha de chamada 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 de CRT, etc.)
0x00320FF8 -8 0xBAADF00D 0x00000031 0xDDDDDDDD 0xFEEEFEEE A solicitação nº aumenta a partir de 0
0x00320FFC -4 0xBAADF00D 0xFDFDFDFD 0xDDDDDDDD 0xFEEEFEEE Nenhuma terra do homem
0x00321000 +0 0xBAADF00D 0xCDCDCDCD 0xDDDDDDDD 0xFEEEFEEE Os 8 bytes que você queria
0x00321004 +4 0xBAADF00D 0xCDCDCDCD 0xDDDDDDDD 0xFEEEFEEE Os 8 bytes que você queria
0x00321008 +8 0xBAADF00D 0xFDFDFDFD 0xDDDDDDDD 0xFEEEFEEE Nenhuma terra do homem
0x0032100C +12 0xBAADF00D 0xBAADF00D 0xDDDDDDDD 0xFEEEFEEE As alocações de heap do Win32 são arredondadas para 16 bytes
0x00321010 +16 0xABABABAB 0xABABABAB 0xABABABAB 0xFEEEFEEE Escrituração de heap do Win32
0x00321014 +20 0xABABABAB 0xABABABAB 0xABABABAB 0xFEEEFEEE Escrituração de heap do Win32
0x00321018 +24 0x00000010 0x00000010 0x00000010 0xFEEEFEEE Escrituração de heap do Win32
0x0032101C +28 0x00000000 0x00000000 0x00000000 0xFEEEFEEE Escrituração de heap do Win32
0x00321020 +32 0x00090051 0x00090051 0x00090051 0xFEEEFEEE Escrituração de heap do Win32
0x00321024 +36 0xFEEE0400 0xFEEE0400 0xFEEE0400 0xFEEEFEEE Escrituração de heap do Win32
0x00321028 +40 0x00320400 0x00320400 0x00320400 0xFEEEFEEE Escrituração de heap do Win32
0x0032102C +44 0x00320400 0x00320400 0x00320400 0xFEEEFEEE Escrituração de heap do Win32
John Dibling
fonte
5

No que diz respeito 0xCCe 0xCD, em particular, estes são relíquias do Intel 8088 / 8086 conjunto de instruções do processador de volta na década de 1980. 0xCCé um caso especial do código de interrupção do software . A versão especial de byte único permite que um programa gere interrupção 3 .INT 0xCD0xCC

Embora os números de interrupção de software sejam, em princípio, arbitrários, INT 3era tradicionalmente usado para a função de quebra ou ponto de interrupção do depurador , uma convenção que permanece até hoje. Sempre que um depurador é iniciado, ele instala um manipulador de interrupção paraINT 3 que, quando esse código de operação for executado, o depurador seja acionado. Normalmente, ele pausará a programação em execução no momento e mostrará um prompt interativo.

Normalmente, o INTcódigo de operação x86 tem dois bytes: 0xCDseguido pelo número de interrupção desejado de 0 a 255. Agora, embora você poderia emitir 0xCD 0x03para INT 3, a Intel decidiu adicionar um especial version-- 0xCCsem byte adicional - porque um código de operação deve ser apenas um byte para funcionar como um 'byte de preenchimento' confiável para a memória não utilizada.

O objetivo aqui é permitir uma recuperação normal, se o processador saltar por engano na memória que não contém nenhuma instrução pretendida . As instruções de vários bytes não são adequadas para esse propósito, pois um salto incorreto pode ocorrer em qualquer deslocamento de bytes possível, onde teria que continuar com um fluxo de instruções formado adequadamente.

Obviamente, os opcodes de um byte funcionam trivialmente para isso, mas também pode haver exceções peculiares: por exemplo, considerando a sequência de preenchimento 0xCDCDCDCD(também mencionada nesta página), podemos ver que é razoavelmente confiável, pois não importa onde o ponteiro da instrução esteja ( exceto, talvez, o último byte preenchido), a CPU pode continuar executando uma instrução x86 de dois bytes válida CD CD, nesse caso, para gerar a interrupção 205 do software (0xCD).

Mais estranho ainda, embora CD CC CD CCseja 100% interpretável - dando uma INT 3ou outra INT 204- a sequência CC CD CC CDé menos confiável, apenas 75% como mostrado, mas geralmente 99,99% quando repetida como um preenchimento de memória de tamanho int.

página do manual contemporâneo do conjunto de instruções 8088/8086 mostrando a instrução INT
Referência do Macro Assembler , 1987

Glenn Slayden
fonte
Uau, eu não percebi (conectar os dois) 0xCC era INT3. Isso faz sentido (ou seja, não por coincidência). Eu costumava injetar "NOP + INT3" em locais onde existem JMPs para inspecionar os registros antes que eles pulassem em algumas ocasiões (muito tempo atrás). Obrigado por esta visão, mistério resolvido!
precisa saber é o seguinte
Para que foi NOP? Não seria suficiente inserir um único 0xCCbyte com o ebcomando (inserir bytes)?
Glenn Slayden
Apenas um hábito, na época, algum código lia dois bytes e tentava usá-lo como tabela de salto ou, em alguns casos, quando listo o código do assembly, adicionando NOP, ele não seria exibido como '???' ou algo (mais legível) ao desmontar; no geral, por várias razões, tornou-se um hábito injetar um NOP antes ou depois do BRK; oh em alguns casos, alguns aplicativos tentaria fazer checksum do bloco de endereços, então eu equilibrar a JMP $ xyzw com INT3 + [some-hex] sorriso
HidekiAI