Was sind in Visual Studio C ++ die Speicherzuordnungsdarstellungen?

216

In Visual Studio hatten wir alle "baadf00d", haben "CC" und "CD" gesehen, als wir zur Laufzeit Variablen im Debugger in C ++ überprüft haben.

Soweit ich weiß, befindet sich "CC" nur im DEBUG-Modus, um anzuzeigen, wann ein Speicher neu () oder alloc () und unitilialisiert wurde. Während "CD" für gelöschten oder freigegebenen Speicher steht. Ich habe nur "baadf00d" in RELEASE Build gesehen (aber ich kann mich irren).

Hin und wieder geraten wir in die Situation, Speicherlecks, Pufferüberläufe usw. zu beheben, und diese Art von Informationen ist praktisch.

Wäre jemand so freundlich, darauf hinzuweisen, wann und in welchen Modi der Speicher für Debugging-Zwecke auf erkennbare Bytemuster eingestellt ist?

HidekiAI
quelle
@ Lưu Vĩnh Phúc: Es ist nicht das Betriebssystem, es ist der Debugger. Das "D" (wie bei 0xCD und 0xDD) steht für Debug (dh malloc_dbg wird über malloc aufgerufen, wie in msdn.microsoft.com/en-us/library/aa270812(v=vs.60).aspx erläutert ). Ich glaube, es fügt auch Zaun / Pfosten um die Haufen hinzu, um Pufferüberläufe zu verfolgen. Es ist sehr nützlich, Probleme zu erkennen, wenn Sie einen Fehler beim doppelten oder mehrfachen Löschen (oder sogar beim möglichen Aufrufen von delete anstelle von delete []) und bei baumelnden Zeigern haben, die entsorgt wurden, und wenn Sie die Daten überprüfen, ist es "0xDD". (oder wenn nicht initialisierter Heap 0xCD zeigt)
HidekiAI
Ich habe nicht gesagt, dass es das Betriebssystem ist. Es ist der andere Fragesteller, der das Tittle falsch geschrieben hat
phuclv

Antworten:

317

Dieser Link enthält weitere Informationen:

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

* 0xABABABAB: Wird von HeapAlloc () von Microsoft verwendet, um Schutzbytes für Niemandsland nach dem zugewiesenen Heapspeicher zu markieren
* 0xABADCAFE: Ein Start auf diesen Wert, um den gesamten freien Speicher zu initialisieren und fehlerhafte Zeiger abzufangen
* 0xBAADF00D: Wird von Microsoft LocalAlloc (LMEM_FIXED) verwendet, um nicht initialisierten zugewiesenen Heapspeicher zu markieren
* 0xBADCAB1E: Fehlercode, der an den Microsoft eVC-Debugger zurückgegeben wird, wenn die Verbindung zum Debugger getrennt wird
* 0xBEEFCACE: Wird von Microsoft .NET als magische Zahl in Ressourcendateien verwendet
* 0xCCCCCCCC: Wird von der C ++ - Debugging-Laufzeitbibliothek von Microsoft verwendet, um nicht initialisierten Stapelspeicher zu markieren
* 0xCDCDCDCD: Wird von der C ++ - Debugging-Laufzeitbibliothek von Microsoft verwendet, um nicht initialisierten Heapspeicher zu markieren
* 0xDDDDDDDD: Wird vom C ++ - Debugging-Heap von Microsoft verwendet, um freigegebenen Heapspeicher zu markieren
* 0xDEADDEAD: Ein Microsoft Windows STOP-Fehlercode, der verwendet wird, wenn der Benutzer den Absturz manuell initiiert.
* 0xFDFDFDFD: Wird vom C ++ - Debugging-Heap von Microsoft verwendet, um Schutzbytes für Niemandsland vor und nach dem zugewiesenen Heapspeicher zu markieren
* 0xFEEEFEEE: Wird von HeapFree () von Microsoft verwendet, um freigegebenen Heapspeicher zu markieren
Mark Ingram
quelle
19
Hier sehe ich BAADF00D(schlechtes Essen), BEEFCACE(Rindfleischkuchen), BAADCAB1E(schlechtes Kabel), BADCAFE(schlechtes Café) und DEADDEAD(tot tot). Ist das beabsichtigt?
Anderson Green
38
@ AndersonGreen Natürlich ist es beabsichtigt. Es heißt Hexspeak .
28
Wir haben C0CAC01A verwendet, als wir damals eine Low-Level-Programmierung (Betriebssystem-Kernel) durchgeführt haben ...;)
Per Lundberg
2
0xDEADBEEF, 0xC0EDBABEauch Klassiker, auch wenn sie nicht in die Umgangssprache der MS fielen
J. Paulding
3
Als Paul McCartney-Fan BEA71E5
mag
111

Es gibt tatsächlich eine Menge nützlicher Informationen, die zu Debug-Zuordnungen hinzugefügt werden. Diese Tabelle ist vollständiger:

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

Adressversatz nach HeapAlloc () nach malloc () während free () nach HeapFree () Kommentare
0x00320FD8 -40 0x01090009 0x01090009 0x01090009 0x0109005A Win32-Heap-Informationen
0x00320FDC -36 0x01090009 0x00180700 0x01090009 0x00180400 Win32-Heap-Informationen
0x00320FE0 -32 0xBAADF00D 0x00320798 0xDDDDDDDD 0x00320448 Ptr zum nächsten CRT-Heap-Block (früher zugewiesen)
0x00320FE4 -28 0xBAADF00D 0x00000000 0xDDDDDDDD 0x00320448 Ptr zum vorherigen CRT-Heapblock (später zugewiesen)
0x00320FE8 -24 0xBAADF00D 0x00000000 0xDDDDDDDD 0xFEEEFEEE Dateiname des Aufrufs malloc ()
0x00320FEC -20 0xBAADF00D 0x00000000 0xDDDDDDDD 0xFEEEFEEE Zeilennummer des malloc () -Aufrufs
0x00320FF0 -16 0xBAADF00D 0x00000008 0xDDDDDDDD 0xFEEEFEEE Anzahl der Bytes für malloc ()
0x00320FF4 -12 0xBAADF00D 0x00000001 0xDDDDDDDD 0xFEEEFEEE-Typ (0 = freigegeben, 1 = normal, 2 = CRT-Verwendung usw.)
0x00320FF8 -8 0xBAADF00D 0x00000031 0xDDDDDDDD 0xFEEEFEEE Request #, erhöht sich von 0
0x00320FFC -4 0xBAADF00D 0xFDFDFDFD 0xDDDDDDDD 0xFEEEFEEE Niemandsland
0x00321000 +0 0xBAADF00D 0xCDCDCDCD 0xDDDDDDDD 0xFEEEFEEE Die 8 Bytes, die Sie wollten
0x00321004 +4 0xBAADF00D 0xCDCDCDCD 0xDDDDDDDD 0xFEEEFEEE Die 8 Bytes, die Sie wollten
0x00321008 +8 0xBAADF00D 0xFDFDFDFD 0xDDDDDDDD 0xFEEEFEEE Niemandsland
0x0032100C +12 0xBAADF00D 0xBAADF00D 0xDDDDDDDD 0xFEEEFEEE Win32-Heap-Zuordnungen werden auf 16 Byte aufgerundet
0x00321010 +16 0xABABABAB 0xABABABAB 0xABABABAB 0xFEEEFEEE Win32-Heap-Buchhaltung
0x00321014 +20 0xABABABAB 0xABABABAB 0xABABABAB 0xFEEEFEEE Win32-Heap-Buchhaltung
0x00321018 +24 0x00000010 0x00000010 0x00000010 0xFEEEFEEE Win32-Heap-Buchhaltung
0x0032101C +28 0x00000000 0x00000000 0x00000000 0xFEEEFEEE Win32-Heap-Buchhaltung
0x00321020 +32 0x00090051 0x00090051 0x00090051 0xFEEEFEEE Win32-Heap-Buchhaltung
0x00321024 +36 0xFEEE0400 0xFEEE0400 0xFEEE0400 0xFEEEFEEE Win32-Heap-Buchhaltung
0x00321028 +40 0x00320400 0x00320400 0x00320400 0xFEEEFEEE Win32-Heap-Buchhaltung
0x0032102C +44 0x00320400 0x00320400 0x00320400 0xFEEEFEEE Win32-Heap-Buchhaltung
John Dibling
quelle
5

In Bezug 0xCCund 0xCDinsbesondere sind diese Relikte aus der Intel 8088 / 8086 - Prozessor - Befehlssatz zurück in den 1980er Jahren. 0xCCist ein Sonderfall des Software-Interrupt- Opcodes . Die spezielle Einzelbyte-Version ermöglicht es einem Programm, Interrupt 3 zu generieren .INT 0xCD0xCC

Obwohl Software-Interrupt-Nummern im Prinzip willkürlich sind, INT 3wurde sie traditionell für die Debugger-Break- oder Breakpoint- Funktion verwendet, eine Konvention, die bis heute besteht. Jedes Mal, wenn ein Debugger gestartet wird, installiert er einen Interrupt-Handler INT 3, sodass der Debugger ausgelöst wird, wenn dieser Opcode ausgeführt wird. In der Regel wird die aktuell ausgeführte Programmierung angehalten und eine interaktive Eingabeaufforderung angezeigt.

Normalerweise besteht der x86- INTOpcode aus zwei Bytes: 0xCDgefolgt von der gewünschten Interrupt-Nummer von 0-255. Nun , obwohl Sie könnten ausgeben 0xCD 0x03für INT 3Intel ein spezielles version-- hinzuzufügen entschieden 0xCCohne zusätzliches Byte - weil ein Opcode nur ein Byte, um zu funktionieren als zuverlässiger ‚Füllbytezeiger‘ für nicht genutzte Speicher sein muss.

Hier geht es darum, eine ordnungsgemäße Wiederherstellung zu ermöglichen, wenn der Prozessor versehentlich in einen Speicher springt, der keine beabsichtigten Anweisungen enthält . Mehrbyte-Befehle sind für diesen Zweck nicht geeignet, da ein fehlerhafter Sprung bei jedem möglichen Byte-Versatz landen könnte, wo er mit einem ordnungsgemäß gebildeten Befehlsstrom fortgesetzt werden müsste.

Offensichtlich funktionieren Ein-Byte-Opcodes hierfür trivial, aber es kann auch eigenartige Ausnahmen geben: Wenn 0xCDCDCDCDwir beispielsweise die Füllsequenz (ebenfalls auf dieser Seite erwähnt) betrachten, können wir sehen, dass sie ziemlich zuverlässig ist, da unabhängig davon, wo der Befehlszeiger landet ( außer vielleicht dem zuletzt gefüllten Byte) kann die CPU die Ausführung eines gültigen Zwei-Byte- x86-Befehls fortsetzen CD CD, in diesem Fall zum Erzeugen des Software-Interrupts 205 (0xCD).

Noch seltsamer, während die Sequenz zu CD CC CD CC100% interpretierbar ist - entweder INT 3oder INT 204-, CC CD CC CDist die Sequenz weniger zuverlässig, nur 75% wie gezeigt, aber im Allgemeinen 99,99%, wenn sie als Speicherfüller mit int-Größe wiederholt wird.

Seite aus der zeitgenössischen 8088/8086-Bedienungsanleitung mit INT-Anleitung
Macro Assembler Reference , 1987

Glenn Slayden
quelle
Wow, ich wusste nicht (verbinde die beiden) 0xCC war INT3. Das macht Sinn (dh nicht zufällig). Ich habe "NOP + INT3" an Stellen injiziert, an denen JMPs vorhanden sind, um Register zu überprüfen, bevor sie bei einigen Gelegenheiten (vor langer Zeit) gesprungen sind. Vielen Dank für diesen Einblick, Rätsel gelöst!
HidekiAI
Wofür war das NOP? Würde die Eingabe eines einzelnen 0xCCBytes mit dem ebBefehl (Bytes eingeben) nicht ausreichen?
Glenn Slayden
Damals war es nur eine Gewohnheit, dass ein Code zwei Bytes las und versuchte, ihn als Sprungtabelle zu verwenden, oder in einigen Fällen, wenn ich den Assembler-Code durch Hinzufügen von NOP auflistete, wurde er nicht als '???' oder etwas (besser lesbares) beim Zerlegen; Alles in allem wurde es aus mehreren Gründen zur Gewohnheit, vor oder nach dem BRK nur einen NOP zu injizieren. Oh, in einigen Fällen würden einige Apps versuchen, eine Prüfsumme des Adressblocks zu erstellen, also würde ich das JMP $ XYZW mit INT3 + [etwas Hex] Grinsen
ausgleichen