У 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.