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

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

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

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

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

@ Lu 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 23.02.2016 21:19

Я не сказал, что это ОС. Это другой спрашивающий неправильно написал титр

phuclv 24.02.2016 02:40
Библиотека для работы с мороженым
Библиотека для работы с мороженым
Лично я попрощался с операторами print() в python. Без шуток.
225
4
109 166
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

По этой ссылке есть дополнительная информация:

https://en.wikipedia.org/wiki/Magic_number_(programming)#Debug_values

* 0xABABABAB : Used by Microsoft's HeapAlloc() to mark "no man's land" guard bytes after allocated heap memory
* 0xABADCAFE : A startup to this value to initialize all free memory to catch errant pointers
* 0xBAADF00D : Used by Microsoft's LocalAlloc(LMEM_FIXED) to mark uninitialised allocated heap memory
* 0xBADCAB1E : Error Code returned to the Microsoft eVC debugger when connection is severed to the debugger
* 0xBEEFCACE : Used by Microsoft .NET as a magic number in resource files
* 0xCCCCCCCC : Used by Microsoft's C++ debugging runtime library to mark uninitialised stack memory
* 0xCDCDCDCD : Used by Microsoft's C++ debugging runtime library to mark uninitialised heap memory
* 0xDDDDDDDD : Used by Microsoft's C++ debugging heap to mark freed heap memory
* 0xDEADDEAD : A Microsoft Windows STOP Error code used when the user manually initiates the crash.
* 0xFDFDFDFD : Used by Microsoft's C++ debugging heap to mark "no man's land" guard bytes before and after allocated heap memory
* 0xFEEEFEEE : Used by Microsoft's HeapFree() to mark freed heap memory

Здесь я вижу BAADF00D (плохая еда), BEEFCACE (говяжий пирог), BAADCAB1E (плохой кабель), BADCAFE (плохое кафе) и DEADDEAD (мертвый мертвец). Это намеренно?

Anderson Green 16.02.2013 08:23

@AndersonGreen Конечно, это сделано намеренно. Он называется хексспик.

user142019 09.05.2013 18:20

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

Per Lundberg 04.09.2013 16:36

0xDEADBEEF, 0xC0EDBABE тоже классика, даже если они не попали в жаргон MS.

J. Paulding 08.04.2015 21:52

0xFD также заполняется флуд-заполнением отладочной версией семейства MS strncat_s, чтобы указать байты целевой строки, в которые не было записано.

ajs410 14.05.2015 18:44

@ ajs410 Да, это так. И это нарушает некоторые реализации, в которых strncat не записывал больше памяти, чем необходимо, и функция заменяется вариантом _s. Старая реализация просто полагалась на старое поведение, которое могло быть недокументировано, но проверено.

harper 06.06.2015 19:55

Как фанат Пола Маккартни, мне нравится BEA71E5.

BlueRaja - Danny Pflughoeft 06.06.2015 21:22

0xCCCCCCCC используется не только для отметки неинициализированной памяти стека, но также как канареечное значение для обнаружения переполнения и опустошения буфера в стеке, когда указан параметр / RTCs.

Hadi Brais 15.10.2017 05:47

Я не знаю, почему vs не может показать какое-нибудь удобочитаемое сообщение! @Microsoft

Albert.Qing 08.07.2019 11:18

@ Albert.Qing Для разработчиков на C++ это доступно для чтения человеком. (Или не считать разработчиков C++ людьми?) ;-) (Между тем, переключаюсь на шестнадцатеричный. Это первое, что я делаю, когда вижу неожиданные странные значения переменных в отладчике VS). Серьезно, как сохранить читаемый человеком сообщение в переменную типа int или double? Hexspeak - это решение ...

Scheff 09.07.2019 09:48

@PerLundberg 0xC0CAC01A? Подсознательная реклама - везде.

Varad Mahashabde 06.01.2020 21:43

@VaradMahashabde :) github.com/chaos4ever/chaos/blob/…

Per Lundberg 07.01.2020 13:15

Это как ... супер полезно (без сарказма). Спасибо большое

Aviv Cohn 17.03.2020 01:18

На самом деле в отладочные распределения добавлено довольно много полезной информации. Эта таблица более полная:

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

Address  Offset After HeapAlloc() After malloc() During free() After HeapFree() Comments
0x00320FD8  -40    0x01090009    0x01090009     0x01090009    0x0109005A     Win32 heap info
0x00320FDC  -36    0x01090009    0x00180700     0x01090009    0x00180400     Win32 heap info
0x00320FE0  -32    0xBAADF00D    0x00320798     0xDDDDDDDD    0x00320448     Ptr to next CRT heap block (allocated earlier in time)
0x00320FE4  -28    0xBAADF00D    0x00000000     0xDDDDDDDD    0x00320448     Ptr to prev CRT heap block (allocated later in time)
0x00320FE8  -24    0xBAADF00D    0x00000000     0xDDDDDDDD    0xFEEEFEEE     Filename of malloc() call
0x00320FEC  -20    0xBAADF00D    0x00000000     0xDDDDDDDD    0xFEEEFEEE     Line number of malloc() call
0x00320FF0  -16    0xBAADF00D    0x00000008     0xDDDDDDDD    0xFEEEFEEE     Number of bytes to malloc()
0x00320FF4  -12    0xBAADF00D    0x00000001     0xDDDDDDDD    0xFEEEFEEE     Type (0=Freed, 1=Normal, 2=CRT use, etc)
0x00320FF8  -8     0xBAADF00D    0x00000031     0xDDDDDDDD    0xFEEEFEEE     Request #, increases from 0
0x00320FFC  -4     0xBAADF00D    0xFDFDFDFD     0xDDDDDDDD    0xFEEEFEEE     No mans land
0x00321000  +0     0xBAADF00D    0xCDCDCDCD     0xDDDDDDDD    0xFEEEFEEE     The 8 bytes you wanted
0x00321004  +4     0xBAADF00D    0xCDCDCDCD     0xDDDDDDDD    0xFEEEFEEE     The 8 bytes you wanted
0x00321008  +8     0xBAADF00D    0xFDFDFDFD     0xDDDDDDDD    0xFEEEFEEE     No mans land
0x0032100C  +12    0xBAADF00D    0xBAADF00D     0xDDDDDDDD    0xFEEEFEEE     Win32 heap allocations are rounded up to 16 bytes
0x00321010  +16    0xABABABAB    0xABABABAB     0xABABABAB    0xFEEEFEEE     Win32 heap bookkeeping
0x00321014  +20    0xABABABAB    0xABABABAB     0xABABABAB    0xFEEEFEEE     Win32 heap bookkeeping
0x00321018  +24    0x00000010    0x00000010     0x00000010    0xFEEEFEEE     Win32 heap bookkeeping
0x0032101C  +28    0x00000000    0x00000000     0x00000000    0xFEEEFEEE     Win32 heap bookkeeping
0x00321020  +32    0x00090051    0x00090051     0x00090051    0xFEEEFEEE     Win32 heap bookkeeping
0x00321024  +36    0xFEEE0400    0xFEEE0400     0xFEEE0400    0xFEEEFEEE     Win32 heap bookkeeping
0x00321028  +40    0x00320400    0x00320400     0x00320400    0xFEEEFEEE     Win32 heap bookkeeping
0x0032102C  +44    0x00320400    0x00320400     0x00320400    0xFEEEFEEE     Win32 heap bookkeeping

Что касается, в частности, 0xCC и 0xCD, то они являются пережитками инструкции процессора Intel 8088 / 8086, установленной еще в 1980-х годах. 0xCC является частным случаем кода операции программное прерываниеINT0xCD. Специальная однобайтовая версия 0xCC позволяет программе генерировать прерывание 3.

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

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

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

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

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

page from contemporaneous 8088/8086 instruction set manual showing INT instruction
Macro Assembler Reference, 1987

Вау, я не понял (соединить два) 0xCC был INT3. В этом есть смысл (т.е.не случайно). Я имел обыкновение вводить "NOP + INT3" в места, где есть JMP, для проверки регистров, прежде чем он несколько раз перескакивал (когда-то давным-давно). Спасибо за понимание, тайна раскрыта!

HidekiAI 20.01.2018 17:54

Для чего был NOP? Разве недостаточно ввода одного байта 0xCC с помощью команды eb (введите байты)?

Glenn Slayden 21.01.2018 02:34

Просто привычка, тогда какой-то код читал два байта и пытался использовать их как таблицу переходов, или в некоторых случаях, когда я перечисляю ассемблерный код, добавляя NOP, он не отображался как '???' или что-то (более разборчивое) при разборке; в общем, по множеству причин просто стало привычкой вводить NOP до или после BRK; о, в некоторых случаях некоторые приложения будут пытаться выполнить контрольную сумму блока адресов, поэтому я бы сбалансировал JMP $ XYZW с помощью INT3 + [some-hex] ухмылка

HidekiAI 05.02.2018 16:45

Другие вопросы по теме