ConstructiCat Logo
CodeBust.
Browse section ▾

Магическое число (программирование).

Числовое значение с неясным смыслом

В программировании магическое число или сигнатура файла — это числовой литерал в исходном коде, который имеет особое, конкретное значение, не вполне очевидное для читателя. Также в вычислительной технике, но не только в программировании, этим термином называют число, идентифицирующее определённое понятие, смысл которого без дополнительных знаний остаётся неясным. Например, некоторые форматы файлов распознаются по встроенному магическому числу в самом файле). Кроме того, число, относительно однозначно связанное с определённым понятием, например универсальный уникальный идентификатор, также может быть отнесено к магическим числам.

Числовой литерал

Магическое число или магическая константа — это числовой литерал в исходном коде, имеющий особое значение, которое не вполне ясно из контекста. Это считается антипаттерном и нарушает одно из старейших правил программирования, восходящее к руководствам по COBOL, FORTRAN и PL/1 1960-х годов.

Например, в следующем коде, вычисляющем цену с учётом налога, 1.05 является магическим числом, поскольку это значение неочевидным образом кодирует ставку налога с продаж, равную 5 %.

price_after_tax = 1.05 * price

Использование магических чисел в коде скрывает намерения разработчиков при выборе этого числа, увеличивает вероятность незаметных ошибок и затрудняет дальнейшую адаптацию и расширение программы. Например, трудно определить, верно ли набрана каждая цифра в 3.14159265358979323846, или же эту константу для числа пи можно усечь до 3.14159 без ущерба для работы программы при пониженной точности. Замена всех значимых магических чисел именованными константами (которые также называют поясняющими переменными) делает программы более простыми для чтения, понимания и сопровождения.

Приведённый выше пример можно улучшить, добавив переменную с описательным именем:

TAX = 0.05
price_after_tax = (1.0 + TAX) * price

Удачное имя позволяет получить код, который легче понять сопровождающему разработчику, не являющемуся автором, и даже самому автору спустя некоторое время. Пример неинформативно названной константы — int SIXTEEN = 16, тогда как int NUMBER_OF_BITS = 16 может оказаться более полезным.

Нечисловые данные могут обладать теми же «магическими» свойствами, а значит, и теми же проблемами, что и магические числа. Так, объявление const string testUserName = "John" и использование testUserName может быть предпочтительнее, чем использование литерала "John" напрямую.

Пример

Например, если требуется случайным образом перемешать значения в массиве, представляющем стандартную колоду игральных карт, этот псевдокод решает задачу с помощью алгоритма тасования Фишера — Йейтса:

for i from 1 to 52
    j := i + randomInt(53 - i) - 1
    a.swapEntries(i, j)

где a — объект-массив, функция randomInt(x) выбирает случайное целое число от 1 до x включительно, а swapEntries(i, j) меняет местами i-й и j-й элементы массива. В предыдущем примере 52 и 53 — магические числа, к тому же явно не связанные друг с другом. Считается, что лучше писать так:

int deckSize:= 52
for i from 1 to deckSize
    j := i + randomInt(deckSize + 1 - i) - 1
    a.swapEntries(i, j)

Это предпочтительнее по нескольким причинам:

  • Лучшая читаемость. Программист, читающий первый пример, может задаться вопросом: что здесь означает число 52? Почему 52? Он может понять смысл, внимательно прочитав код, но это неочевидно. Магические числа становятся особенно запутанными, когда одно и то же число используется для разных целей в одном фрагменте кода.
  • Проще в сопровождении. Изменить значение числа легче, поскольку оно не дублируется. Изменение значения магического числа чревато ошибками, потому что одно и то же значение часто используется несколько раз в разных местах программы. Кроме того, когда две семантически различные переменные или числа имеют одно и то же значение, их могут случайно отредактировать вместе. Чтобы изменить первый пример для тасования колоды Таро, в которой 78 карт, программист может наивно заменить каждое вхождение 52 в программе на 78. Это привело бы к двум проблемам. Во-первых, было бы пропущено значение 53 во второй строке примера, из-за чего алгоритм незаметно дал бы сбой. Во-вторых, скорее всего, символы «52» были бы заменены повсюду, независимо от того, обозначают ли они размер колоды или нечто совершенно иное, например число недель в григорианском календарном году, или, что ещё коварнее, являются частью числа вроде «1523», — и всё это внесло бы ошибки. Напротив, изменение значения переменной deckSize во втором примере было бы простым изменением в одну строку.
  • Поощряет документирование. Единственное место, где объявляется именованная переменная, — удачное место, чтобы задокументировать, что означает это значение и почему оно именно такое. Наличие одного и того же значения во множестве мест либо приводит к дублированию комментариев (и сопутствующим проблемам, когда часть из них обновляют, а часть упускают), либо не оставляет ни одного места, где автору было бы естественно объяснить значение и где читатель, вероятно, станет искать объяснение.
  • Объединяет информацию. Объявления переменных-«магических чисел» можно разместить вместе, обычно в начале функции или файла, что упрощает их просмотр и изменение.
  • Обнаруживает опечатки. Использование переменной (вместо литерала) задействует проверку компилятора. Случайно набранное «62» вместо «52» осталось бы незамеченным, тогда как набранное «dekSize» вместо «deckSize» привело бы к предупреждению компилятора о том, что dekSize не объявлена.
  • Сокращает набор текста. Если IDE поддерживает автодополнение кода, она подставит большую часть имени переменной по первым нескольким буквам.
  • Облегчает параметризацию. Например, чтобы обобщить приведённый выше пример в процедуру, тасующую колоду из любого числа карт, достаточно превратить deckSize в параметр этой процедуры, тогда как первый пример потребовал бы нескольких изменений.
function shuffle (int deckSize)
   for i from 1 to deckSize
       j := i + randomInt(deckSize + 1 - i) - 1
       a.swapEntries(i, j)

Недостатки:

  • Нарушает локальность. Когда именованная константа определена не рядом с местом её использования, это вредит локальности, а значит, и понятности кода. Размещение 52 в потенциально отдалённом месте означает, что для полного понимания работы цикла «for» (например, чтобы оценить время его выполнения) приходится разыскивать определение и проверять, что это ожидаемое число. Этого легко избежать (перенеся объявление), когда константа используется лишь в одной части кода. Когда же именованная константа используется в разрозненных частях, отдалённое местоположение служит читателю подсказкой, что то же значение встречается и в других местах кода, которые, возможно, тоже стоит изучить.
  • Приводит к многословию. Объявление константы добавляет строку. Когда имя константы длиннее её значения, особенно если несколько таких констант появляются в одной строке, может потребоваться разбить один логический оператор кода на несколько строк. Увеличение многословия может быть оправдано, когда есть вероятность путаницы относительно константы или когда константу, возможно, придётся изменить, например при повторном использовании процедуры тасования для других карточных игр. Оно может быть в равной мере оправдано как повышение выразительности.
  • Соображения производительности. Обработка выражения deckSize + 1 во время выполнения может быть медленнее, чем использование значения «53». Тем не менее большинство современных компиляторов применяют такие методы, как свёртка констант и оптимизация циклов, чтобы вычислить сложение при компиляции, поэтому по сравнению с использованием магических чисел в коде потери в скорости обычно отсутствуют или пренебрежимо малы. В особенности стоимость отладки и время, затрачиваемое на попытки понять не поясняющий код, нужно сопоставлять с ничтожной стоимостью вычисления.

Допустимое использование

Когда числовой литерал не несёт особого смысла, его использование не считается «магическим», хотя то, что считать особым, субъективно. Примеры литералов, которые часто не считают магическими:

  • Использование 0 и 1 в качестве начальных или приращиваемых значений в цикле for, например for (int i = 0; i < max; i += 1)
  • Использование 2 для проверки чётности числа, как в isEven = (x % 2 == 0), где % — оператор взятия остатка
  • Использование степеней 10 для перевода метрических величин (например, между граммами и килограммами) или для вычисления процентов и значений в промилле
  • Показатели степени в выражениях вроде (f(x) ** 2 + f(y) ** 2) ** 0.5 для
  • Литералы 1 и 0 иногда используют для представления булевых значений true и false. Возможно, присваивание этих значений именам вроде TRUE и FALSE было бы лучше.
  • В C и C++ 0 часто используется для обозначения нулевого указателя, хотя стандартная библиотека C определяет макрос NULL, а современный C++ включает ключевое слово nullptr.

Индикатор формата

Происхождение

Индикаторы формата впервые использовались в раннем исходном коде Version 7 Unix.

Unix был перенесён на одну из первых машин DEC PDP-11/20, не имевшую защиты памяти. Поэтому ранние версии Unix использовали модель перемещаемых ссылок на память. Версии Unix до Sixth Edition считывали исполняемый файл в память и переходили к первому младшему адресу программы — относительному адресу ноль. С разработкой страничных версий Unix был создан заголовок для описания компонентов исполняемого образа. Кроме того, первым словом заголовка вставлялась команда перехода, чтобы пропустить заголовок и начать выполнение программы. Таким образом, программа могла выполняться как в старом режиме перемещаемых ссылок на память (обычном), так и в страничном режиме. По мере разработки новых форматов исполняемых файлов добавлялись новые константы путём увеличения смещения перехода.

В исходном коде Sixth Edition загрузчика программ Unix функция exec() считывала исполняемый (двоичный) образ из файловой системы. Первые 8 байт файла составляли заголовок, содержащий размеры областей программы (текста) и инициализированных (глобальных) данных. Кроме того, первое 16-битное слово заголовка сравнивалось с двумя константами, чтобы определить, содержит ли исполняемый образ перемещаемые ссылки на память (обычный), недавно реализованный страничный образ только для чтения или образ с раздельными страницами команд и данных. О двойной роли константы заголовка не упоминалось, но старший байт константы фактически был кодом операции команды перехода PDP-11 (восьмеричное 000407 или шестнадцатеричное 0107). Прибавление семёрки к счётчику команд показывало, что если эта константа будет выполнена, она направит службу exec() Unix за восьмибайтовый заголовок исполняемого образа и запустит программу.

Поскольку Sixth и Seventh Edition Unix использовали страничный код, двойная роль константы заголовка была скрыта. То есть служба exec() считывала (мета)данные заголовка исполняемого файла в буфер пространства ядра, но сам исполняемый образ читала в пространство пользователя, тем самым не используя функцию перехода константы. Создание магического числа было реализовано в компоновщике и загрузчике Unix, а переход по магическому числу, вероятно, всё ещё использовался в наборе автономных диагностических программ, поставлявшихся с Sixth и Seventh Edition. Таким образом, константа заголовка создавала иллюзию и отвечала критериям магии.

В Version Seven Unix константа заголовка не проверялась напрямую, а присваивалась переменной с меткой ux_mag и впоследствии называлась магическим числом. Вероятно, из-за своей уникальности термин магическое число стал означать тип формата исполняемого файла, затем расширился до типа файловой системы, а потом снова — до любого типа файла.

В файлах

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

Примеры
  • Скомпилированные файлы классов Java (байт-код) и двоичные файлы Mach-O начинаются с шестнадцатеричного CA FE BA BE. При сжатии с помощью Pack200 байты меняются на CA FE D0 0D.
  • Файлы изображений GIF содержат ASCII-код строки "GIF89a" (47 49 46 38 39 61) или "GIF87a" (47 49 46 38 37 61)
  • Файлы изображений JPEG начинаются с FF D8 и заканчиваются FF D9. Файлы JPEG/JFIF содержат строку с завершающим нулём "JFIF" (4A 46 49 46 00). Файлы JPEG/Exif содержат строку с завершающим нулём "Exif" (45 78 69 66 00), за которой следуют другие метаданные о файле.
  • Файлы изображений PNG начинаются с 8-байтовой сигнатуры, которая идентифицирует файл как PNG и позволяет обнаружить распространённые проблемы передачи файлов: "\211PNG\r\n\032\n" (89 50 4E 47 0D 0A 1A 0A). Эта сигнатура содержит различные символы перевода строки, позволяющие обнаружить нежелательные автоматические преобразования переводов строк, например при передаче файла по FTP в текстовом режиме передачи вместо двоичного.
  • Стандартные аудиофайлы MIDI содержат ASCII-код строки "MThd" (MIDI Track header, 4D 54 68 64), за которым следуют другие метаданные.
  • Скрипты Unix или Linux могут начинаться с shebang ("#!", 23 21), за которым следует путь к интерпретатору, если интерпретатор, вероятно, отличается от того, из которого был вызван скрипт.
  • Исполняемые файлы ELF начинаются с байта 7F, за которым следует "ELF" (7F 45 4C 46).
  • Файлы и программы PostScript начинаются с "%!" (25 21).
  • Файлы PDF начинаются с "%PDF" (шестнадцатеричное 25 50 44 46).
  • Файлы DOS MZ executable и EXE-заглушка файлов PE (Portable Executable) Microsoft Windows начинаются с символов "MZ" (4D 5A) — инициалов создателя формата файла, Марка Збиковски. Определение допускает и нечасто встречающееся "ZM" (5A 4D) для dosZMXP, не-PE EXE.
  • Формат суперблока Berkeley Fast File System идентифицируется как 19 54 01 19 или 01 19 54 в зависимости от версии; оба представляют дату рождения автора, Маршалла Кирка Маккьюсика.
  • Главная загрузочная запись загрузочных накопителей практически на всех IA-32 IBM PC-совместимых компьютерах имеет код 55 AA в качестве двух последних байт.
  • Исполняемые файлы для портативных игровых систем Game Boy и Game Boy Advance имеют магическое число длиной 48 или 156 байт соответственно в фиксированном месте заголовка. Это магическое число кодирует растровое изображение логотипа Nintendo.
  • Исполняемые Hunk-файлы программ Amiga, работающие на классических машинах Amiga 68000, все начинались с шестнадцатеричного числа $000003f3, прозванного "Magic Cookie".
  • В Amiga единственный абсолютный адрес в системе — шестнадцатеричный $0000 0004 (ячейка памяти 4), который содержит начальный адрес под названием SysBase — указатель на exec.library, так называемое ядро Amiga.
  • Файлы PEF, используемые классической Mac OS и BeOS для исполняемых файлов PowerPC, содержат ASCII-код строки "Joy!" (4A 6F 79 21) в качестве префикса.
  • Файлы TIFF начинаются с "II" или "MM", за которыми следует 42 в виде двухбайтового целого с порядком байтов от младшего или старшего. "II" — для Intel, использующего порядок от младшего байта, поэтому магическое число — 49 49 2A 00. "MM" — для Motorola, использующей порядок от старшего байта, поэтому магическое число — 4D 4D 00 2A.
  • Текстовые файлы Unicode, закодированные в UTF-16, часто начинаются с метки порядка байтов для определения порядка байтов (FE FF для старшего байта и FF FE для младшего). А в Microsoft Windows текстовые файлы UTF-8 часто начинаются с кодировки UTF-8 того же символа — EF BB BF.
  • Файлы LLVM Bitcode начинаются с "BC" (42 43).
  • Файлы WAD начинаются с "IWAD" или "PWAD" (для Doom), "WAD2" (для Quake) и "WAD3" (для Half-Life).
  • Файлы Compound File Binary Format от Microsoft (наиболее известного как один из старых форматов документов Microsoft Office) начинаются с D0 CF 11 E0, что визуально напоминает слово "DOCFILE0".
  • Заголовки в ZIP-файлах часто отображаются в текстовых редакторах как "PK♥♦" (50 4B 03 04), где "PK" — инициалы Фила Каца, автора DOS-утилиты сжатия PKZIP.
  • Заголовки в 7z-файлах начинаются с "7z" (полное магическое число: 37 7A BC AF 27 1C).
Обнаружение

Утилита Unix file может считывать и интерпретировать магические числа из файлов, а файл, используемый для разбора этой информации, называется magic. Утилита Windows TrID имеет схожее назначение.

В протоколах

Примеры
  • Протокол OSCAR, используемый в AIM/ICQ, предваряет запросы байтом 2A.
  • В протоколе RFB, используемом VNC, клиент начинает обмен с сервером, отправляя "RFB" (52 46 42, от "Remote Frame Buffer"), за которым следует номер версии протокола клиента.
  • В протоколе SMB, используемом Microsoft Windows, каждый запрос SMB или ответ сервера начинается с FF 53 4D 42, или \xFFSMB в начале запроса SMB.
  • В протоколе MSRPC, используемом Microsoft Windows, каждый запрос на основе TCP начинается с 05 в начале запроса (что представляет Microsoft DCE/RPC версии 5), за которым сразу следует 00 или 01 для младшей версии. В запросах MSRPC на основе UDP первый байт всегда 04.
  • В маршалированных интерфейсах COM и DCOM, называемых OBJREF, всегда начинаются с последовательности байтов "MEOW" (4D 45 4F 57). Отладочные расширения (используемые для перехвата канала DCOM) предваряются последовательностью байтов "MARB" (4D 41 52 42).
  • Незашифрованные запросы к BitTorrent-трекеру начинаются с одного байта со значением 19, представляющего длину заголовка, за которым сразу следует фраза "BitTorrent protocol" в позиции байта 1.
  • Трафик eDonkey2000/eMule начинается с одного байта, представляющего версию клиента. В настоящее время E3 представляет клиент eDonkey, C5 — eMule, а D4 — сжатый eMule.
  • Первые 4 байта блока в блокчейне Bitcoin содержат магическое число, служащее идентификатором сети. Значение D9 B4 BE F9 указывает на основную сеть, тогда как DA B5 BF FA указывает на тестовую сеть.
  • Транзакции SSL всегда начинаются с сообщения "client hello". Схема инкапсуляции записей, используемая для префикса всех пакетов SSL, состоит из двух- и трёхбайтовых форм заголовка. Обычно сообщение client hello SSL версии 2 предваряется байтом 80, а ответ сервера SSLv3 на client hello начинается с 16 (хотя это может варьироваться).
  • Пакеты DHCP используют значение "magic cookie" 63 82 53 63 в начале секции параметров пакета. Это значение включается во все типы пакетов DHCP.
  • Соединения HTTP/2 начинаются с 24-символьной строки PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n. Она призвана предотвратить обработку кадров серверами и посредниками, которые поддерживают более ранние версии HTTP, но не 2.0.
  • Рукопожатие при открытии WebSocket использует строку, содержащую UUIDv4 258EAFA5-E914-47DA-95CA-C5AB0DC85B11.

В интерфейсах

Магические числа распространены в функциях API и интерфейсах во многих операционных системах, включая DOS, Windows и NetWare:

Примеры
  • IBM PC-совместимые BIOS используют магические значения 00 00 и 12 34, чтобы решить, нужно ли при перезагрузке пересчитывать память, выполняя тем самым холодную или горячую загрузку. Эти значения также используются менеджерами памяти EMM386, перехватывающими запросы на загрузку. BIOS также используют магические значения 55 AA, чтобы определить, является ли диск загрузочным.
  • Дисковый кэш MS-DOS SMARTDRV (с кодовым названием "Bambi") использует магические значения BA BE и EB AB в функциях API.
  • Многие драйверы DR-DOS, Novell DOS и OpenDOS, разработанные в бывшем European Development Centre в Великобритании, используют значение 0E DC в качестве магического токена при вызове или предоставлении дополнительной функциональности поверх (эмулируемых) стандартных функций DOS, одним из примеров чего является NWCACHE.

Другие применения

Примеры

GUID

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

Идентификаторы продуктов Microsoft Windows для продуктов Microsoft Office иногда заканчиваются на 0000-0000-0000000FF1CE ("OFFICE"), например 90160000-008C-0000-0000-0000000FF1CE — идентификатор продукта "Office 16 Click-to-Run Extensibility Component".

Java использует несколько GUID, начинающихся с CAFEEFAC.

В таблице разделов GUID схемы разметки GPT загрузочные разделы BIOS используют специальный GUID 21686148-6449-6E6F-744E-656564454649, который не следует определению GUID; вместо этого он образован из ASCII-кодов строки Hah!IdontNeedEFI, частично в порядке от младшего байта.

Отладочное значение

Магические отладочные значения — это специальные значения, записываемые в память во время выделения или освобождения, чтобы впоследствии можно было определить, не были ли они повреждены, и сделать очевидным использование значений из неинициализированной памяти. Память обычно просматривают в шестнадцатеричном виде, поэтому распространены запоминающиеся повторяющиеся значения или значения в стиле hexspeak. Могут предпочитаться численно нечётные значения, чтобы процессоры без побайтовой адресации давали сбой при попытке использовать их как указатели (которые должны попадать на чётные адреса). Следует выбирать значения, далёкие от вероятных адресов (кода программы, статических данных, данных кучи или стека). Аналогично их могут выбирать так, чтобы они не были допустимыми кодами в наборе команд данной архитектуры.

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

Известные и распространённые примеры:

Код Описание
00008123 Используется в MS Visual C++. Удалённые указатели устанавливаются в это значение, чтобы при последующем использовании они генерировали исключение; это более узнаваемый псевдоним для нулевого адреса. Активируется параметром Security Development Lifecycle (/sdl).
..FACADE "Facade", используется рядом ОСРВ.
1BADB002 "1 bad boot", магическое число заголовка Multiboot.
8BADF00D "Ate bad food", указывает, что приложение Apple iOS было завершено из-за срабатывания сторожевого таймера.
A5A5A5A5 Используется во встраиваемой разработке, поскольку чередующийся битовый шаблон (1010 0101) создаёт легко узнаваемую картину на осциллографах и логических анализаторах.
A5 Используется в FreeBSD в PHK malloc(3) для отладки, когда /etc/malloc.conf символически связан с "-J", чтобы инициализировать всю вновь выделенную память этим значением, так как оно не является нулевым указателем или ASCII-символом NUL.
ABABABAB Используется отладочной функцией HeapAlloc() от Microsoft для пометки защитных байтов «ничейной земли» после выделенной памяти кучи.
ABADBABE "A bad babe", используется Apple как магическое число "Boot Zero Block".
ABBABABE "ABBA babe", используется кучей памяти игры Driver: Parallel Lines.
ABADCAFE "A bad cafe", используется для инициализации всей невыделенной памяти (Mungwall, AmigaOS).
B16B00B5 "Big Boobs", ранее требовалось гипервизором Hyper-V от Microsoft для использования гостевыми системами Linux в качестве старшей половины их "guest id".
BAADF00D "Bad food", используется отладочной функцией HeapAlloc() от Microsoft для пометки неинициализированной выделенной памяти кучи.
BAAAAAAD "Baaaaaad", указывает, что журнал Apple iOS является снимком стека всей системы, а не отчётом о сбое.
BAD22222 "Bad too repeatedly", указывает, что VoIP-приложение Apple iOS было завершено, поскольку возобновлялось слишком часто.
BADBADBADBAD "Bad bad bad bad", «неинициализированная» память Burroughs Large Systems (48-битные слова).
BADC0FFEE0DDF00D "Bad coffee odd food", используется на 64-битных системах IBM RS/6000 для обозначения неинициализированных регистров ЦП.
BADDCAFE "Bad cafe", в Solaris от Sun Microsystems помечает неинициализированную память ядра (KMEM_UNINITIALIZED_PATTERN).
BBADBEEF "Bad beef", используется в WebKit для особенно неустранимых ошибок.
BEBEBEBE Используется AddressSanitizer для заполнения выделенной, но не инициализированной памяти.
BEEFCACE "Beef cake", используется Microsoft .NET как магическое число в файлах ресурсов.
C00010FF "Cool off", указывает, что приложение Apple iOS было закрыто операционной системой в ответ на тепловое событие.
CAFEBABE "Cafe babe", используется Java для файлов классов.

Используется в многоархитектурных двоичных файлах Mach-O.

CAFED00D "Cafe dude", используется Java для сжатия pack200.
CAFEFEED "Cafe feed", используется отладочным ядром Solaris от Sun Microsystems для пометки памяти kmemfree().
CCCCCCCC Используется отладочной библиотекой времени выполнения C++ от Microsoft и многими средами DOS для пометки неинициализированной памяти стека. CC — это код операции прерывания отладочной точки останова INT 3 на процессорах x86.
CDCDCDCD Используется отладочной функцией malloc() C/C++ от Microsoft для пометки неинициализированной памяти кучи, обычно возвращаемой из HeapAlloc.
0D15EA5E "Zero Disease", используется как флаг, указывающий на обычную загрузку на консолях GameCube и Wii.
DDDDDDDD Используется SmartHeap от MicroQuill и отладочной функцией free() C/C++ от Microsoft для пометки освобождённой памяти кучи.
DEAD10CC "Dead lock", указывает, что приложение Apple iOS было завершено, поскольку удерживало системный ресурс, работая в фоновом режиме.
DEADBABE "Dead babe", используется в начале файлов arena IRIX от Silicon Graphics.
DEADBEEF "Dead beef", широко используется на системах IBM, таких как RS/6000, а также в операционных системах классической Mac OS, OPENSTEP Enterprise и Commodore Amiga. В Solaris от Sun Microsystems помечает освобождённую память ядра (KMEM_FREE_PATTERN).
DEADCAFE "Dead cafe", используется Microsoft .NET как номер ошибки в DLL.
DEADC0DE "Dead code", используется как маркер в прошивке OpenWRT, чтобы обозначить начало создаваемой файловой системы jffs2 в конце статической прошивки.
DEADFA11 "Dead fail", указывает, что приложение Apple iOS было принудительно закрыто пользователем.
DEADF00D "Dead food", используется Mungwall на Commodore Amiga для пометки выделенной, но неинициализированной памяти.
DEFEC8ED "Defecated", используется для дампов памяти OpenSolaris.
DEADDEAD "Dead Dead" указывает, что пользователь намеренно инициировал дамп аварийного завершения из отладчика ядра или с клавиатуры под управлением Microsoft Windows.
D00D2BAD "Dude, Too Bad", используется при сбоях Safari в macOS Big Sur.
D00DF33D "Dude feed", используется деревом устройств (devicetree) для обозначения начала заголовков.
EBEBEBEB Из SmartHeap от MicroQuill.
FADEDEAD "Fade dead", ставится в конце для идентификации каждого скрипта AppleScript.
FDFDFDFD Используется отладочной функцией malloc() C/C++ от Microsoft для пометки защитных байтов «ничейной земли» до и после выделенной памяти кучи, а также некоторыми отладочными функциями Secure C-Runtime, реализованными Microsoft (например, strncat_s).
FEE1DEAD "Feel dead", используется системным вызовом reboot() в Linux.
FEEDFACE "Feed face", встречается в двоичных файлах Mach-O на платформе Mac OSX от Apple Inc. В Solaris от Sun Microsystems помечает красную зону (KMEM_REDZONE_PATTERN).

Используется VLC player и некоторыми IP-камерами в протоколе RTP/RTCP; VLC player отправляет четыре байта в порядке байтов системы. Некоторые IP-камеры ожидают, что плеер отправит это магическое число, и не запускают поток, если оно не получено.

FEEEFEEE "Fee fee", используется отладочной функцией HeapFree() от Microsoft для пометки освобождённой памяти кучи. У некоторых близлежащих внутренних служебных значений старшее слово также может быть установлено в FEEE.

Большинство из них имеют длину 32 битаразмер машинного слова большинства компьютеров с 32-битной архитектурой.

Распространённость этих значений в технологиях Microsoft не случайна; они подробно рассматриваются в книге Стива Магуайра Writing Solid Code, выпущенной Microsoft Press. Он приводит ряд критериев для таких значений, например:

  • Они не должны быть полезными; то есть от большинства алгоритмов, работающих с ними, следует ожидать чего-то необычного. Числа вроде нуля этому критерию не соответствуют.
  • Программист должен легко распознавать их в отладчике как недопустимые значения.
  • На машинах без выравнивания байтов они должны быть нечётными числами, чтобы разыменование их как адресов вызывало исключение.
  • Они должны вызывать исключение или, возможно, даже останов отладчика при выполнении в качестве кода.

Поскольку их часто использовали для пометки областей памяти, которые по сути были пусты, некоторые из этих терминов стали употребляться в выражениях со значением «исчез, прерван, вытеснен из памяти»; например, "Твоя программа — DEADBEEF".