Visual Studio C ++では、メモリ割り当て表現は何ですか?


216

Visual Studioでは、実行時にC ++のデバッガーで変数を検査するときに、「baadf00d」、「CC」、「CD」が表示されました。

私が理解しているところによると、 "CC"はDEBUGモードにあり、メモリがnew()またはalloc()であり、ユニット化されたことを示します。「CD」は、削除または解放されたメモリを表します。RELEASEビルドで「baadf00d」だけを見たことがあります(ただし、間違っている可能性があります)。

ときどき、メモリリークやバッファオーバーフローなどに対処する状況に陥り、これらの種類の情報が役に立ちます。

いつ、どのモードでメモリがデバッグ目的で認識可能なバイトパターンに設定されるかを誰かが指摘してくれるでしょうか?



@LưuVĩnhPhúc:これはOSではなく、デバッガです。"D"(0xCDおよび0xDDと同様)はデバッグ用です(つまり、malloc_dbgは、msdn.microsoft.com / en-us / library / aa270812(v = vs.60).aspxで説明されているようにmallocを介して呼び出されます)。バッファオーバーランを追跡するためにヒープの周りにフェンス/ポストも追加すると思います。double-deleteまたはmultiple-free(またはdelete []ではなくdeleteの呼び出しの可能性さえある)のバグがあり、破棄されたダングリングポインターがあり、データを検査するときに「0xDD」である場合、問題を検出すると非常に役立ちます。 (または初期化されていないヒープが0xCDを示している場合)
HidekiAI

OSだとは言わなかった。タイトルを間違って書いたのは、他の質問者です
phuclv

回答:


317

このリンクには詳細情報があります:

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

* 0xABABABAB:MicrosoftのHeapAlloc()によって使用され、ヒープメモリが割り当てられた後に「人の土地ではない」ガードバイトをマークします。
* 0xABADCAFE:誤ったポインタをキャッチするためにすべての空きメモリを初期化するこの値へのスタートアップ
* 0xBAADF00D:MicrosoftのLocalAlloc(LMEM_FIXED)によって使用され、初期化されていない割り当て済みヒープメモリにマークを付けます
* 0xBADCAB1E:デバッガーへの接続が切断されたときにMicrosoft eVCデバッガーに返されるエラーコード
* 0xBEEFCACE:Microsoft .NETがリソースファイルのマジックナンバーとして使用
* 0xCCCCCCCC:MicrosoftのC ++デバッグランタイムライブラリが未初期化スタックメモリをマークするために使用
* 0xCDCDCDCD:初期化されていないヒープメモリをマークするために、MicrosoftのC ++デバッグランタイムライブラリによって使用されます。
* 0xDDDDDDDD:解放されたヒープメモリをマークするために、MicrosoftのC ++デバッグヒープによって使用されます。
* 0xDEADDEAD:ユーザーが手動でクラッシュを開始したときに使用されるMicrosoft Windows STOPエラーコード。
* 0xFDFDFDFD:MicrosoftのC ++デバッグヒープが、割り当てられたヒープメモリの前後に「人の土地ではない」ガードバイトをマークするために使用します。
* 0xFEEEFEEE:解放されたヒープメモリをマークするためにMicrosoftのHeapFree()によって使用されます

19
ここでは、BAADF00D(不良食品)、BEEFCACE(牛肉ケーキ)、 BAADCAB1E(不良ケーブル)、BADCAFE(不良カフェ)、DEADDEAD(デッドデッド)が表示されます。これは意図的ですか?
アンダーソングリーン

38
@AndersonGreenもちろん、それは意図的なものです。それはhexspeakと呼ばれています

28
かつて低レベル(オペレーティングシステムカーネル)プログラミングを行っていたときは、C0CAC01Aを使用していました...;)
Per Lundberg

2
0xDEADBEEF0xC0EDBABEMSの専門用語に該当しなかったとしてもクラシック
J.ポールディング

3
ポールマッカートニーのファンとして、私は好きですBEA71E5
BlueRaja-Danny Pflughoeft

111

実際には、割り当てのデバッグに役立つ情報がかなり追加されています。この表はより完全です:

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

HeapAlloc()後のアドレスオフセットmalloc()後free()後HeapFree()コメント
0x00320FD8 -40 0x01090009 0x01090009 0x01090009 0x0109005A Win32ヒープ情報
0x00320FDC -36 0x01090009 0x00180700 0x01090009 0x00180400 Win32ヒープ情報
0x00320FE0 -32 0xBAADF00D 0x00320798 0xDDDDDDDD 0x00320448次のCRTヒープブロックへのPtr(以前に割り当てられた)
0x00320FE4 -28 0xBAADF00D 0x00000000 0xDDDDDDDD 0x00320448前のCRTヒープブロックへのPtr(後で割り当て)
0x00320FE8 -24 0xBAADF00D 0x00000000 0xDDDDDDDD 0xFEEEFEEE malloc()呼び出しのファイル名
0x00320FEC -20 0xBAADF00D 0x00000000 0xDDDDDDDD 0xFEEEFEEE malloc()呼び出しの行番号
0x00320FF0 -16 0xBAADF00D 0x00000008 0xDDDDDDDD 0xFEEEFEEE malloc()するバイト数
0x00320FF4 -12 0xBAADF00D 0x00000001 0xDDDDDDDD 0xFEEEFEEEタイプ(0 =解放、1 =通常、2 = CRT使用など)
0x00320FF8 -8 0xBAADF00D 0x00000031 0xDDDDDDDD 0xFEEEFEEE要求番号、0から増加
0x00320FFC -4 0xBAADF00D 0xFDFDFDFD 0xDDDDDDDD 0xFEEEFEEE陸地なし
0x00321000 +0 0xBAADF00D 0xCDCDCDCD 0xDDDDDDDD 0xFEEEFEEE必要な8バイト
0x00321004 +4 0xBAADF00D 0xCDCDCDCD 0xDDDDDDDD 0xFEEEFEEE必要な8バイト
0x00321008 +8 0xBAADF00D 0xFDFDFDFD 0xDDDDDDDD 0xFEEEFEEE陸地なし
0x0032100C +12 0xBAADF00D 0xBAADF00D 0xDDDDDDDD 0xFEEEFEEE Win32ヒープ割り当ては16バイトに切り上げられます
0x00321010 +16 0xABABABAB 0xABABABAB 0xABABABAB 0xFEEEFEEE Win32ヒープブックキーピング
0x00321014 +20 0xABABABAB 0xABABABAB 0xABABABAB 0xFEEEFEEE Win32ヒープブックキーピング
0x00321018 +24 0x00000010 0x00000010 0x00000010 0xFEEEFEEE Win32ヒープ簿記
0x0032101C +28 0x00000000 0x00000000 0x00000000 0xFEEEFEEE Win32ヒープブックキーピング
0x00321020 +32 0x00090051 0x00090051 0x00090051 0xFEEEFEEE Win32ヒープ簿記
0x00321024 +36 0xFEEE0400 0xFEEE0400 0xFEEE0400 0xFEEEFEEE Win32ヒープブックキーピング
0x00321028 +40 0x00320400 0x00320400 0x00320400 0xFEEEFEEE Win32ヒープブックキーピング
0x0032102C +44 0x00320400 0x00320400 0x00320400 0xFEEEFEEE Win32ヒープブックキーピング

5

0xCC及び0xCD特に、これらからの遺物であるインテル8088 / 8086 1980におけるプロセッサ命令セットバック。ソフトウェア割り込みオペコードの 0xCC特殊なケースです。特別な1バイトバージョンでは、プログラムが割り込み3を生成できます。INT 0xCD0xCC

ソフトウェア割り込み番号は、原則として任意ですINT 3が、伝統的にデバッガのブレークまたはブレークポイント機能に使用されていましたが、この慣習は今日まで残っています。デバッガーが起動されるたびに、INT 3そのオペコードが実行されるとデバッガーがトリガーされるように、割り込みハンドラーがインストールされます。通常、現在実行中のプログラミングを一時停止し、インタラクティブなプロンプトを表示します。

通常、x86 INTオペコードは2バイトです0xCD。0〜255の範囲の目的の割り込み番号が続きます。で発行できますが、未使用のメモリの信頼できる「フィルバイト」として機能するためには、オペコードが1バイトのみでなければならない0xCD 0x03ためINT 3、インテルは特別なバージョンを追加することを決定しました0xCC

ここでのポイントは、プロセッサが意図した命令を含まないメモリに誤ってジャンプした場合に、正常な回復を可能にすることです。マルチバイト命令は、誤ったジャンプが適切に形成された命令ストリームで続行しなければならない可能性のあるバイトオフセットに到達する可能性があるため、この目的には適していません。

明らかに、1バイトのオペコードはこれで問題なく機能しますが、風変わりな例外が発生する可能性もあります。たとえば、塗りつぶしシーケンス0xCDCDCDCD(このページでも説明)を考えると、命令ポインターがどこにあるかに関わらず、かなり信頼できることがわかりますおそらく最後に満たされたバイトを除いて)、CPUは有効な2バイト x86命令の実行を再開できます。CD CDこの場合、ソフトウェア割り込み205(0xCD)を生成します。

さらに奇妙なことに、CD CC CD CC100%は解釈可能ですが、どちらINT 3かを与えると、INT 204シーケンスのCC CD CC CD信頼性は低下します(図のように75%だけです)。

同時発生の8088/8086命令セットマニュアルのINT命令を示すページ
マクロアセンブラリファレンス、1987


うわー、私は(2つを接続する)0xCCがINT3であることに気付きませんでした。それは理にかなっています(つまり、偶然ではありません)。レジスターを検査するJMPがある場所に "NOP + INT3"を挿入して、それが数回ジャンプする前に(いつか戻る)レジスタを検査していました。この洞察をありがとう、謎は解決しました!
HidekiAI 2018年

何のNOPために?(0xCCバイトをeb入力する)コマンドで1 バイトを入力するだけで十分でしょうか?
Glenn Slayden

ただの習慣ですが、当時のコードでは、2バイトを読み取ってジャンプテーブルとして使用しようとしたり、場合によっては、アセンブリコードを一覧表示するときにNOPを追加したり、「???」と表示されなかったりします。または分解するときに何か(より読みやすい)。全体として、複数の理由により、BRKの前または後にNOPを注入することが習慣になりました。場合によっては、一部のアプリがアドレスブロックのチェックサムを実行しようとするため、JMP $ XYZWとINT3 + [some-hex] grin
HidekiAI
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.