У Visual Studio C ++, що таке представлення розподілу пам'яті?


216

У Visual Studio всі ми мали "baadf00d", бачили "CC" та "CD" під час перевірки змінних у відладчику в C ++ під час роботи.

Як я розумію, "CC" перебуває в режимі DEBUG лише для того, щоб вказати, коли пам'ять була новою () або alloc () та неіціалізованою. У той час як "CD" являє собою пам'ять видалення або звільнення. Я бачив лише "baadf00d" у збірці RELEASE (але я можу помилятися).

Час від часу ми потрапляємо в ситуацію усунення витоків пам’яті, переповнення буфера тощо, і така інформація стає в нагоді.

Хтось буде досить люб'язним, щоб вказати, коли і в яких режимах пам'ять встановлена ​​на розпізнавані шаблони байтів для налагодження?



@ Lưu Vĩnh Phúc: Це не ОС, це налагоджувач. "D" (як на 0xCD і 0xDD) призначений для налагодження (тобто malloc_dbg - це те, що викликається через malloc, як пояснено в msdn.microsoft.com/en-us/library/aa270812(v=vs.60).aspx ). Я вважаю, що це також додає огорожу / пости навколо купи для відстеження перекриття буфера. Дуже корисно вирішувати проблеми, коли у вас є помилка подвійного видалення або безлічі безкоштовного (або навіть можливе виклик видалення замість видалення []) та вивішених покажчиків, які були видалені, і коли ви перевіряєте дані, це "0xDD" (або коли неініціалізована купа показує 0xCD)
HidekiAI

Я не сказав, що це ОС. Це інший
запитувач,

Відповіді:


317

У цьому посиланні є додаткова інформація:

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

* 0xABABABAB: Використовується HeapAlloc () Microsoft для позначення байтів охоронних байтів "нічия земля" після виділеної пам'яті купи
* 0xABADCAFE: запуск цього значення для ініціалізації всієї вільної пам’яті для лову помилкових покажчиків
* 0xBAADF00D: використовується LocalAlloc Microsoft (LMEM_FIXED) Microsoft для позначення неініціалізованої виділеної пам'яті купи
* 0xBADCAB1E: Код помилки повертається у відладчик Microsoft eVC, коли з'єднання розривається на відладчик
* 0xBEEFCACE: Використовується Microsoft .NET як чарівне число у файлах ресурсів
* 0xCCCCCCCC: Використовується бібліотекою виконання налагодження C ++ Microsoft для позначення неініціалізованої пам'яті стека
* 0xCDCDCDCD: Використовується бібліотекою виконання налагодження C ++ Microsoft для позначення неініціалізованої пам'яті купи
* 0xDDDDDDDD: використовується на налагоджувальній купі налагодження C ++ Microsoft для маркування звільненої пам'яті купи
* 0xDEADDEAD: код помилки STOP Microsoft Windows, який використовується, коли користувач вручну ініціює збій.
* 0xFDFDFDFD: Використовується налагоджувальною купою налагодження C ++ Microsoft для позначення байтів охоронних байтів "нічия земля" до та після виділеної пам'яті купи
* 0xFEEEFEEE: використовується Microsoft HeapFree () для позначення звільненої пам'яті купи

20
Тут я бачу BAADF00D(погана їжа), BEEFCACE(яловичий пиріг), BAADCAB1E(поганий кабель), BADCAFE(поганий кафе) та DEADDEAD(мертвий мертвий). Це навмисно?
Андерсон Грін

38
@AndersonGreen Звичайно, це навмисно. Це називається шістнадцятковий .

28
Раніше ми використовували C0CAC01A, коли ми робили програмування на низькому рівні (ядро операційної системи) ще за днів ...;)
Пер Лундберг

2
0xDEADBEEF, 0xC0EDBABEтакож класика, навіть якщо б вони не потрапили до загальної мови MS
Дж. Полдінг,

3
Як фанат Пола Маккартні, я захоплююсьBEA71E5
BlueRaja - Danny Pflughoeft

111

Насправді досить багато корисної інформації, що додається до виділень налагодження. Ця таблиця є більш повною:

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

Зміщення адреси після HeapAlloc () Після malloc () Під час вільного () Після HeapFree () Коментарі
0x00320FD8 -40 0x01090009 0x01090009 0x01090009 0x0109005A Інформація про купу Win32
0x00320FDC -36 0x01090009 0x00180700 0x01090009 0x00180400 Інформація про купу Win32
0x00320FE0 -32 0xBAADF00D 0x00320798 0xDDDDDDDD 0x00320448 Ptr до наступного блоку купівлі CRT (виділено раніше)
0x00320FE4 -28 0xBAADF00D 0x00000000 0xDDDDDDDD 0x00320448 Ptr до попереднього блоку купівлі CRT (виділено пізніше)
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зокрема, ці реліквії від Intel 8088 / 8086 набір команд процесора ще в 1980 - х роках. 0xCCє особливим випадком програмного коду переривання . Спеціальна однобайтова версія дозволяє програмі генерувати переривання 3 .INT 0xCD0xCC

Хоча номери програмного переривання, в принципі, довільні, INT 3традиційно використовувались для функції налагодження відключення або точки відключення , умовою, яка залишається донині. Щоразу, коли налагоджувач запускається, він встановлює обробник переривання для INT 3такого, що при виконанні цього коду відладчик буде спрацьовувати. Зазвичай він призупиняє програмування, що виконується в даний час, і показує інтерактивну підказку.

Як правило, x86 INTопкод - це два байти: 0xCDслідом за потрібним номером переривання від 0-255. Тепер, хоча можна було випустити 0xCD 0x03для цього INT 3, Intel вирішила додати спеціальну версію - 0xCCбез додаткового байту - тому що для коду повинен бути лише один байт, щоб він міг функціонувати як надійний "байт заповнення" для невикористаної пам'яті.

Суть у тому, щоб дозволити витончене відновлення, якщо процесор помилково стрибне в пам'ять, яка не містить жодних передбачених інструкцій . Багатобайтові вказівки не підходять для цієї мети, оскільки помилковий стрибок може приземлитися при будь-якому можливому зміщенні байтів, де потрібно було б продовжуватись із правильно сформованим потоком інструкцій.

Очевидно, що однобайтові опкоди для цього працюють тривіально, але можуть бути і вигадливі винятки: наприклад, розглядаючи послідовність заповнення 0xCDCDCDCD(також згадувану на цій сторінці), ми можемо побачити, що це досить надійно, оскільки незалежно від того, де розташований вказівник інструкції ( крім, можливо, останнього заповненого байта), процесор може відновити виконання дійсної двобайтової інструкції x86 CD CD, в цьому випадку для створення програмного переривання 205 (0xCD).

Незважаючи на те, що на CD CC CD CC100% можна інтерпретувати - даючи одну INT 3або INT 204- послідовність CC CD CC CDє менш надійною, лише 75%, як показано, але, як правило, 99,99%, коли повторюється як наповнювач пам'яті розміру в інт.

сторінка із сучасного посібника з набору інструкцій 8088/8086, що показує інструкцію INT
Довідник макроассемблера , 1987


Нічого собі, я не зрозумів (з'єднайте два) 0xCC був INT3. Це має сенс (тобто не за збігом обставин). Раніше я вводив "NOP + INT3" у місця, де є JMP, щоб перевірити регістри, перш ніж він стрибнув декілька разів (назад, коли). Дякуємо за це прозріння, розгадану таємницю!
HidekiAI

Для чого було NOP? Чи не введено один 0xCCбайт із командою eb(enter bytes) достатньо?
Гленн Слейден

Просто звичка, тоді якийсь код читав би два байти і намагався використовувати його як таблицю стрибків, або в деяких випадках, коли я перелічу код складання, додаючи NOP, він не відображатиметься як "???" або щось (більш розбірливе) при розбиранні; загалом, з кількох причин просто стало звичкою просто вводити НОП до або після БРК; о, в деяких випадках деякі додатки намагаються зробити контрольну суму блоку адрес, тому я збалансувати JMP $ XYZW з INT3 + [деякою шестигранною] посмішкою
HidekiAI
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.