В Visual Studio C ++, каковы представления распределения памяти?

216

В Visual Studio у всех нас было «baadf00d», мы видели «CC» и «CD» при проверке переменных в отладчике в C ++ во время выполнения.

Из того, что я понимаю, "CC" находится в режиме отладки только для указания, когда память была новой () или alloc () и унитилизована. В то время как «CD» обозначает удаление или освобождение памяти. Я видел только baadf00d в RELEASE build (но я могу ошибаться).

Время от времени мы попадаем в ситуацию с утечками памяти, переполнением буфера и т. Д., И такая информация оказывается полезной.

Будет ли кто-нибудь достаточно любезен, чтобы указать, когда и в каких режимах памяти установлены распознаваемые байтовые шаблоны для целей отладки?

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

Ответы:

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: Используется библиотекой времени выполнения отладки C ++ от Microsoft для маркировки неинициализированной кучи памяти.
* 0xDDDDDDDD: Используется отладочной кучей Microsoft C ++ для отметки свободной памяти кучи
* 0xDEADDEAD: код ошибки Microsoft Windows STOP, используемый, когда пользователь вручную запускает сбой.
* 0xFDFDFDFD: Используется кучей отладки Microsoft C ++ для пометки защитных байтов «без земли» до и после выделенной памяти кучи
* 0xFEEEFEEE: Используется Microsoft HeapFree () для пометки свободной памяти кучи
Марк Инграм
источник
20
Здесь я вижу BAADF00D(плохая еда), BEEFCACE(говяжий пирог), BAADCAB1E(плохой кабель), BADCAFE(плохое кафе) и DEADDEAD(мертвый мертвец). Это намеренно?
Андерсон Грин
38
@AndersonGreen Конечно, это намеренно. Это называется hexspeak .
28
Мы привыкли использовать C0CAC01A, когда делали какое-то низкоуровневое программирование (ядро операционной системы) в те дни ...;)
Per Lundberg
2
0xDEADBEEF, 0xC0EDBABEТакже классика , даже если они не попадают в просторечии МС
J. Paulding
3
Как поклонник Пола Маккартни, я очень люблюBEA71E5
BlueRaja - Дэнни 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 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 = Freed, 1 = Normal, 2 = использование CRT и т. Д.)
0x00320FF8 -8 0xBAADF00D 0x00000031 0xDDDDDDDD 0xFEEEFEEE Request #, увеличивается с 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, чтобы при выполнении этого кода операции был запущен отладчик. Обычно это приостанавливает текущее программирование и отображает интерактивное приглашение.

Обычно INTкод операции x86 составляет два байта: 0xCDза ним следует номер прерывания от 0 до 255. Теперь , хотя вы могли бы выпустить 0xCD 0x03на INT 3, Intel решила добавить специальный version-- 0xCCбез дополнительного байта - потому что опкод должен быть только один байт, чтобы функционировать в качестве надежного «заполнения байта» для неиспользуемой памяти.

Суть здесь в том, чтобы обеспечить постепенное восстановление, если процессор ошибочно переходит в память, которая не содержит каких-либо предполагаемых инструкций . Многобайтовые инструкции не подходят для этой цели, так как ошибочный переход может привести к любому возможному смещению байта, где он должен был бы продолжаться с правильно сформированным потоком команд.

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

Что еще более странно, в то время CD CC CD CCкак 100% интерпретируемо - дает либо INT 3или INT 204- последовательность CC CD CC CDменее надежна, только 75%, как показано, но обычно 99,99%, когда повторяется как заполнитель памяти целого размера.

страница из современной инструкции 8088/8086 с инструкцией INT
Справочник по макросам , 1987

Гленн Слэйден
источник
Ничего себе, я не понял (подключить два) 0xCC был INT3. Это имеет смысл (то есть не случайно). Раньше я вставлял «NOP + INT3» в местах, где есть JMP для проверки регистров, прежде чем он несколько раз перепрыгивал (когда назад). Спасибо за это понимание, тайна раскрыта!
HidekiAI
Что было NOPдля? Разве недостаточно ввода одного 0xCCбайта с помощью команды eb(введите байты)?
Гленн Слэйден
Просто привычка, тогда какой-то код считывал два байта и пытался использовать его в качестве таблицы переходов, или в некоторых случаях, когда я перечисляю код сборки, добавив NOP, он не будет отображаться как «???» или что-то (более разборчивое) при разборке; в целом, по многим причинам, это просто стало привычкой просто вводить NOP до или после BRK; о, в некоторых случаях некоторые приложения пытаются выполнить контрольную сумму блока адресов, поэтому я бы сбалансировал JMP $ XYZW с INT3 + [some-hex] ухмылкой
HidekiAI