Número mágico (programación).
Valor numérico con un significado poco claro
En programación de computadoras, un número mágico o firma de archivo es un literal numérico presente en el código fuente que tiene un significado especial y particular que resulta poco claro para el lector. También en informática, aunque no únicamente en la programación, el término se utiliza para un número que identifica un concepto concreto pero cuyo significado resulta poco claro sin conocimiento adicional. Por ejemplo, algunos formatos de archivo se identifican mediante un número mágico incrustado en el archivo ). Además, un número asociado de forma relativamente única a un concepto particular, como un identificador único universal, podría clasificarse como un número mágico.
Literal numérico
Un número mágico o constante mágica es un literal numérico presente en el código fuente que tiene un significado especial que resulta poco claro en su contexto. Esto se considera un antipatrón e infringe una de las reglas más antiguas de la programación, que se remonta a los manuales de COBOL, FORTRAN y PL/1 de la década de 1960.
Por ejemplo, en el siguiente código que calcula un precio después de impuestos, 1.05 es un número mágico, ya que el valor codifica la tasa del impuesto sobre las ventas, el 5%, de una forma poco evidente.
price_after_tax = 1.05 * price
El uso de números mágicos en el código oculta la intención de los desarrolladores al elegir ese número, aumenta las posibilidades de cometer errores sutiles y dificulta que el programa pueda adaptarse y ampliarse en el futuro. Por ejemplo, resulta difícil saber si todos los dígitos de 3.14159265358979323846 están escritos correctamente, o si esta constante de pi puede truncarse a 3.14159 sin que su menor precisión afecte a la funcionalidad del programa. Sustituir todos los números mágicos significativos por constantes con nombre (también llamadas variables explicativas) hace que los programas sean más fáciles de leer, comprender y mantener.
El ejemplo anterior puede mejorarse añadiendo una variable con un nombre descriptivo:
TAX = 0.05 price_after_tax = (1.0 + TAX) * price
Un buen nombre puede dar lugar a un código que resulte más fácil de entender para quien lo mantiene y no es el autor original, e incluso para el propio autor original al cabo de un tiempo. Un ejemplo de una constante con un nombre poco informativo es int SIXTEEN = 16, mientras que int NUMBER_OF_BITS = 16 podría resultar más útil.
Los datos no numéricos pueden tener las mismas propiedades mágicas y, por tanto, los mismos problemas que los números mágicos. Así pues, declarar const string testUserName = "John" y utilizar testUserName podría ser mejor que emplear directamente el literal "John".
Ejemplo
Por ejemplo, si se necesita barajar aleatoriamente los valores de un arreglo que representa una baraja estándar de naipes, este pseudocódigo realiza la tarea utilizando el algoritmo de barajado de Fisher–Yates:
for i from 1 to 52
j := i + randomInt(53 - i) - 1
a.swapEntries(i, j)
donde a es un objeto de tipo arreglo, la función randomInt(x) elige un entero aleatorio entre 1 y x, ambos incluidos, y swapEntries(i, j) intercambia las entradas i-ésima y j-ésima del arreglo. En el ejemplo anterior, 52 y 53 son números mágicos que, además, no guardan una relación clara entre sí. Se considera un mejor estilo de programación escribir lo siguiente:
int deckSize:= 52
for i from 1 to deckSize
j := i + randomInt(deckSize + 1 - i) - 1
a.swapEntries(i, j)
Esto es preferible por varias razones:
- Mayor legibilidad. Un programador que lea el primer ejemplo podría preguntarse: ¿Qué significa aquí el número 52? ¿Por qué 52? El programador podría deducir el significado tras leer el código con atención, pero no resulta evidente. Los números mágicos resultan especialmente confusos cuando el mismo número se usa con distintos fines en una misma sección de código.
- Más fácil de mantener. Resulta más sencillo modificar el valor del número, ya que no está duplicado. Cambiar el valor de un número mágico es propenso a errores, porque el mismo valor suele utilizarse varias veces en distintos lugares de un programa. Además, cuando dos variables o números semánticamente distintos tienen el mismo valor, podrían editarse ambos por accidente al mismo tiempo. Para modificar el primer ejemplo y barajar una baraja del Tarot, que tiene 78 cartas, un programador podría, de forma ingenua, sustituir cada aparición de 52 en el programa por 78. Esto provocaría dos problemas. En primer lugar, pasaría por alto el valor 53 de la segunda línea del ejemplo, lo que haría que el algoritmo fallara de forma sutil. En segundo lugar, probablemente reemplazaría los caracteres «52» en todas partes, con independencia de si se refieren al tamaño de la baraja o a algo completamente distinto, como el número de semanas de un año del calendario gregoriano o, de forma más insidiosa, si forman parte de un número como «1523», todo lo cual introduciría errores. En cambio, cambiar el valor de la variable
deckSizeen el segundo ejemplo sería una modificación sencilla de una sola línea. - Fomenta la documentación. El único lugar donde se declara la variable con nombre constituye un buen sitio para documentar qué significa el valor y por qué tiene el valor que tiene. Tener el mismo valor en multitud de lugares conduce a comentarios duplicados (con los consiguientes problemas al actualizar algunos y olvidar otros) o no deja ningún único lugar en el que resulte natural que el autor explique el valor y donde sea probable que el lector busque una explicación.
- Agrupa la información. Las declaraciones de las variables de «número mágico» pueden colocarse juntas, normalmente al principio de una función o de un archivo, lo que facilita su revisión y modificación.
- Detecta erratas. Usar una variable (en lugar de un literal) aprovecha la comprobación del compilador. Escribir accidentalmente «62» en vez de «52» pasaría inadvertido, mientras que escribir «
dekSize» en lugar de «deckSize» haría que el compilador advirtiera de quedekSizeno está declarada. - Reduce la escritura. Si un IDE admite el autocompletado de código, rellenará la mayor parte del nombre de la variable a partir de las primeras letras.
- Facilita la parametrización. Por ejemplo, para generalizar el ejemplo anterior en un procedimiento que baraje una baraja con cualquier número de cartas, bastaría con convertir
deckSizeen un parámetro de dicho procedimiento, mientras que el primer ejemplo requeriría varios cambios.
function shuffle (int deckSize)
for i from 1 to deckSize
j := i + randomInt(deckSize + 1 - i) - 1
a.swapEntries(i, j)
Las desventajas son:
- Rompe la localidad. Cuando la constante con nombre no se define cerca de donde se usa, se perjudica la localidad y, por tanto, la comprensibilidad del código. Colocar el 52 en un lugar posiblemente lejano implica que, para entender por completo el funcionamiento del bucle «for» (por ejemplo, para estimar el tiempo de ejecución del bucle), hay que localizar la definición y comprobar que es el número esperado. Esto es fácil de evitar (reubicando la declaración) cuando la constante solo se usa en una parte del código. Cuando la constante con nombre se utiliza en partes dispares, en cambio, la ubicación remota es una pista para el lector de que el mismo valor aparece en otros lugares del código, que también podría merecer la pena revisar.
- Provoca verbosidad. La declaración de la constante añade una línea. Cuando el nombre de la constante es más largo que el valor, en especial si varias de esas constantes aparecen en una misma línea, puede que sea necesario dividir una sentencia lógica del código en varias líneas. Un aumento de la verbosidad puede estar justificado cuando existe cierta probabilidad de confusión respecto a la constante, o cuando es probable que la constante deba cambiarse, como en la reutilización de una rutina de barajado para otros juegos de cartas. Igualmente puede justificarse como un aumento de la expresividad.
- Consideraciones de rendimiento. Procesar la expresión
deckSize + 1en tiempo de ejecución puede ser más lento que el valor «53». Dicho esto, la mayoría de los compiladores modernos utilizan técnicas como el plegado de constantes y la optimización de bucles para resolver la suma durante la compilación, por lo que normalmente no hay penalización de velocidad, o es insignificante, en comparación con el uso de números mágicos en el código. Sobre todo, el coste de la depuración y el tiempo necesario para intentar comprender un código no explicativo deben sopesarse frente al ínfimo coste del cálculo.
Uso aceptado
Cuando un literal numérico carece de un significado especial, su uso no se clasifica como mágico, aunque lo que se considera «especial» es subjetivo. Entre los ejemplos de literales que a menudo no se consideran mágicos se incluyen:
- Uso de 0 y 1 como valores iniciales o de incremento en un bucle for, como
for (int i = 0; i < max; i += 1)
- Uso del 2 para comprobar si un número es par o impar, como en
isEven = (x % 2 == 0), donde%es el operador módulo
- Uso de literales sencillos, p. ej., en expresiones como
circumference = 2 * Math.PI * radius, o para calcular el discriminante de una ecuación cuadrática comod = b^2 − 4*a*c
- Uso de potencias de 10 para convertir valores métricos (por ejemplo, entre gramos y kilogramos) o para calcular valores porcentuales y por mil
- Exponentes en expresiones como
(f(x) ** 2 + f(y) ** 2) ** 0.5para
- Los literales 1 y 0 se utilizan a veces para representar los valores booleanos verdadero y falso. Es discutible, pero asignar estos valores a nombres como TRUE y FALSE podría ser mejor.
- En C y C++, a menudo se usa 0 para significar puntero nulo, aunque la biblioteca estándar de C define una macro
NULLy el C++ moderno incluye una palabra clavenullptr.
Indicador de formato
Origen
Los indicadores de formato se usaron por primera vez en el primer código fuente de Version 7 Unix.
Unix se portó a uno de los primeros PDP-11/20 de DEC, que no disponía de protección de memoria. Por ello, las primeras versiones de Unix usaban el modelo de referencia de memoria reubicable. Las versiones anteriores a Sixth Edition Unix leían un archivo ejecutable en la memoria y saltaban a la primera dirección de memoria baja del programa, la dirección relativa cero. Con el desarrollo de las versiones paginadas de Unix, se creó una cabecera para describir los componentes de la imagen ejecutable. Además, se insertó una instrucción de salto como primera palabra de la cabecera para omitir la cabecera e iniciar el programa. De este modo, un programa podía ejecutarse en el antiguo modo de referencia de memoria reubicable (normal) o en modo paginado. A medida que se desarrollaban más formatos ejecutables, se añadían nuevas constantes incrementando el desplazamiento del salto.
En el código fuente de la Sixth Edition del cargador de programas de Unix, la función exec() leía la imagen ejecutable (binaria) del sistema de archivos. Los primeros 8 bytes del archivo formaban una cabecera que contenía los tamaños del programa (texto) y de las áreas de datos inicializados (globales). Además, la primera palabra de 16 bits de la cabecera se comparaba con dos constantes para determinar si la imagen ejecutable contenía referencias de memoria reubicables (normal), la imagen ejecutable de solo lectura paginada recién implementada, o la imagen paginada con instrucciones y datos separados. No se mencionaba el doble papel de la constante de la cabecera, pero el byte de orden superior de la constante era, de hecho, el código de operación de la instrucción de salto del PDP-11 (000407 en octal o 0107 en hexadecimal). Sumar siete al contador de programa mostraba que, si esta constante se ejecutaba, haría que el servicio exec() de Unix saltara por encima de la cabecera de ocho bytes de la imagen ejecutable e iniciara el programa.
Dado que la Sixth y la Seventh Edition de Unix empleaban código de paginación, el doble papel de la constante de la cabecera quedaba oculto. Es decir, el servicio exec() leía los datos (meta) de la cabecera del archivo ejecutable en un búfer del espacio de núcleo, pero leía la imagen ejecutable en el espacio de usuario, por lo que no usaba la función de salto de la constante. La creación de números mágicos se implementó en el enlazador y el cargador de Unix, y el salto mediante el número mágico probablemente seguía utilizándose en el conjunto de programas de diagnóstico autónomos que acompañaban a la Sixth y la Seventh Edition. Así pues, la constante de la cabecera sí ofrecía una ilusión y cumplía los criterios para ser considerada mágica.
En Version Seven Unix, la constante de la cabecera no se comprobaba directamente, sino que se asignaba a una variable denominada ux_mag y, posteriormente, se la denominaba el número mágico. Probablemente debido a su singularidad, el término número mágico pasó a designar el tipo de formato ejecutable, después se amplió para designar el tipo de sistema de archivos y se amplió de nuevo para designar cualquier tipo de archivo.
En archivos
Los números mágicos son habituales en los programas de muchos sistemas operativos. Los números mágicos implementan datos con tipado fuerte y son una forma de señalización en banda para el programa de control que lee el tipo o los tipos de datos en tiempo de ejecución. Muchos archivos tienen constantes de este tipo que identifican los datos que contienen. Detectar estas constantes en los archivos es una manera sencilla y eficaz de distinguir entre muchos formatos de archivo y puede aportar información adicional en tiempo de ejecución.
- Ejemplos
- Los archivos de clase de Java compilados (bytecode) y los binarios Mach-O comienzan con el hexadecimal
CA FE BA BE. Cuando se comprimen con Pack200, los bytes cambian aCA FE D0 0D. - Los archivos de imagen GIF contienen el código ASCII de «GIF89a» (
47 49 46 38 39 61) o «GIF87a» (47 49 46 38 37 61) - Los archivos de imagen JPEG comienzan con
FF D8y terminan conFF D9. Los archivos JPEG/JFIF contienen la cadena terminada en nulo «JFIF» (4A 46 49 46 00). Los archivos JPEG/Exif contienen la cadena terminada en nulo «Exif» (45 78 69 66 00), seguida de más metadatos sobre el archivo. - Los archivos de imagen PNG comienzan con una firma de 8 bytes que identifica el archivo como un archivo PNG y permite detectar problemas habituales de transferencia de archivos: «\211PNG\r\n\032\n» (
89 50 4E 47 0D 0A 1A 0A). Esa firma contiene varios caracteres de salto de línea para permitir detectar conversiones automáticas e injustificadas de los saltos de línea, como transferir el archivo mediante FTP con el modo de transferencia ASCII en lugar del modo binario. - Los archivos de audio MIDI estándar contienen el código ASCII de «MThd» (MIDI Track header,
4D 54 68 64) seguido de más metadatos. - Los scripts de Unix o Linux pueden comenzar con un shebang («#!»,
23 21) seguido de la ruta a un intérprete, si es probable que el intérprete sea distinto de aquel desde el que se invocó el script. - Los ejecutables ELF comienzan con el byte
7Fseguido de «ELF» (7F 45 4C 46). - Los archivos y programas PostScript comienzan con «%!» (
25 21). - Los archivos PDF comienzan con «%PDF» (hexadecimal
25 50 44 46). - Los archivos ejecutables DOS MZ y el código auxiliar EXE de los archivos PE (Portable Executable) de Microsoft Windows comienzan con los caracteres «MZ» (
4D 5A), las iniciales del diseñador del formato de archivo, Mark Zbikowski. La definición también admite el poco frecuente «ZM» (5A 4D) para dosZMXP, un EXE que no es PE. - El formato del superbloque del Berkeley Fast File System se identifica como
19 54 01 19o01 19 54según la versión; ambos representan la fecha de nacimiento del autor, Marshall Kirk McKusick. - El Master Boot Record de los dispositivos de almacenamiento arrancables en casi todos los compatibles con IBM PC IA-32 tiene el código
55 AAcomo sus dos últimos bytes. - Los ejecutables para las videoconsolas portátiles Game Boy y Game Boy Advance tienen un número mágico de 48 bytes o de 156 bytes, respectivamente, en un lugar fijo de la cabecera. Este número mágico codifica un mapa de bits del logotipo de Nintendo.
- Los archivos ejecutables Hunk del software de Amiga que se ejecutaban en las máquinas clásicas 68000 de Amiga comenzaban todos con el número hexadecimal $000003f3, apodado la «Magic Cookie».
- En el Amiga, la única dirección absoluta del sistema es el hexadecimal $0000 0004 (posición de memoria 4), que contiene la ubicación inicial llamada SysBase, un puntero a exec.library, el llamado núcleo del Amiga.
- Los archivos PEF, utilizados por el Mac OS clásico y BeOS para los ejecutables de PowerPC, contienen el código ASCII de «Joy!» (
4A 6F 79 21) como prefijo. - Los archivos TIFF comienzan con «II» o «MM» seguido de 42 como un entero de dos bytes con orden de bytes little o big endian. «II» corresponde a Intel, que usa el orden de bytes little endian, por lo que el número mágico es
49 49 2A 00. «MM» corresponde a Motorola, que usa el orden de bytes big endian, por lo que el número mágico es4D 4D 00 2A. - Los archivos de texto Unicode codificados en UTF-16 suelen comenzar con la marca de orden de bytes para detectar el endianness (
FE FFpara big endian yFF FEpara little endian). Y en Microsoft Windows, los archivos de texto UTF-8 suelen comenzar con la codificación UTF-8 del mismo carácter,EF BB BF. - Los archivos de Bitcode de LLVM comienzan con «BC» (
42 43). - Los archivos WAD comienzan con «IWAD» o «PWAD» (para Doom), «WAD2» (para Quake) y «WAD3» (para Half-Life).
- Los archivos del Compound File Binary Format de Microsoft (conocido sobre todo como uno de los formatos más antiguos de los documentos de Microsoft Office) comienzan con
D0 CF 11 E0, que visualmente sugiere la palabra «DOCFILE0». - Las cabeceras de los archivos ZIP suelen mostrarse en los editores de texto como «PK♥♦» (
50 4B 03 04), donde «PK» son las iniciales de Phil Katz, autor de la utilidad de compresión de DOS PKZIP. - Las cabeceras de los archivos 7z comienzan con «7z» (número mágico completo:
37 7A BC AF 27 1C).
- Detección
El programa de utilidad de Unix file puede leer e interpretar los números mágicos de los archivos, y el archivo que se usa para analizar la información se llama magic. La utilidad de Windows TrID tiene un propósito similar.
En protocolos
- Ejemplos
- El protocolo OSCAR, usado en AIM/ICQ, antepone
2Aa las solicitudes. - En el protocolo RFB que usa VNC, un cliente inicia su conversación con un servidor enviando «RFB» (
52 46 42, de «Remote Frame Buffer») seguido del número de versión del protocolo del cliente. - En el protocolo SMB que usa Microsoft Windows, cada solicitud SMB o respuesta del servidor comienza con
FF 53 4D 42, o\xFFSMBal inicio de la solicitud SMB. - En el protocolo MSRPC que usa Microsoft Windows, cada solicitud basada en TCP comienza con
05al inicio de la solicitud (que representa la versión 5 de Microsoft DCE/RPC), seguido inmediatamente de un00o un01para la versión menor. En las solicitudes MSRPC basadas en UDP, el primer byte es siempre04. - En las interfaces serializadas de COM y DCOM, llamadas OBJREF, siempre comienzan con la secuencia de bytes «MEOW» (
4D 45 4F 57). Las extensiones de depuración (usadas para interceptar el canal de DCOM) van precedidas de la secuencia de bytes «MARB» (4D 41 52 42). - Las solicitudes sin cifrar al rastreador de BitTorrent comienzan con un único byte que contiene el valor
19, que representa la longitud de la cabecera, seguido inmediatamente de la frase «BitTorrent protocol» en la posición de byte 1. - El tráfico de eDonkey2000/eMule comienza con un único byte que representa la versión del cliente. Actualmente
E3representa un cliente eDonkey,C5representa eMule yD4representa eMule comprimido. - Los primeros 4 bytes de un bloque de la cadena de bloques de Bitcoin contienen un número mágico que sirve como identificador de la red. El valor es
D9 B4 BE F9, que indica la red principal, mientras queDA B5 BF FAindica la red de pruebas (testnet). - Las transacciones SSL siempre comienzan con un mensaje «client hello». El esquema de encapsulación de registros que se usa para anteponer a todos los paquetes SSL consta de formas de cabecera de dos y tres bytes. Normalmente, un mensaje client hello de SSL versión 2 va precedido de un
80y una respuesta de un servidor SSLv3 a un client hello comienza con16(aunque esto puede variar). - Los paquetes DHCP usan un valor de «magic cookie» de
63 82 53 63al inicio de la sección de opciones del paquete. Este valor se incluye en todos los tipos de paquetes DHCP. - Las conexiones HTTP/2 comienzan con la cadena de 24 caracteres
PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n. Está diseñada para evitar el procesamiento de tramas por parte de servidores e intermediarios que admiten versiones anteriores de HTTP, pero no la 2.0. - El protocolo de enlace inicial de WebSocket usa una cadena que contiene el UUIDv4
258EAFA5-E914-47DA-95CA-C5AB0DC85B11.
En interfaces
Los números mágicos son habituales en las funciones de API y las interfaces de muchos sistemas operativos, como DOS, Windows y NetWare:
- Ejemplos
- Las BIOS compatibles con IBM PC usan los valores mágicos
00 00y12 34para decidir si el sistema debe contar la memoria o no al reiniciar, realizando así un arranque en frío o en caliente. Estos valores también los usan los gestores de memoria EMM386 que interceptan las solicitudes de arranque. Las BIOS también usan los valores mágicos55 AApara determinar si un disco es arrancable. - La caché de disco SMARTDRV de MS-DOS (cuyo nombre en clave era «Bambi») usa los valores mágicos
BA BEyEB ABen las funciones de la API. - Muchos controladores de DR-DOS, Novell DOS y OpenDOS desarrollados en el antiguo European Development Centre del Reino Unido usan el valor
0E DCcomo token mágico al invocar o proporcionar funcionalidad adicional que se sitúa por encima de las funciones estándar (emuladas) de DOS, siendo NWCACHE un ejemplo.
Otros usos
- Ejemplos
- La dirección MAC predeterminada en los SoC de Texas Instruments es
DE:AD:BE:EF:00:00.
GUID
Es posible crear o modificar los identificadores globalmente únicos (GUID) para que sean fáciles de recordar, pero esto está muy desaconsejado, ya que compromete su robustez como identificadores casi únicos. Las especificaciones para generar GUID y UUID son bastante complejas, que es lo que hace que sean prácticamente únicos si se implementan correctamente.
Los números de identificación de producto de Microsoft Windows para los productos de Microsoft Office a veces terminan con 0000-0000-0000000FF1CE («OFFICE»), como 90160000-008C-0000-0000-0000000FF1CE, el identificador de producto del «Office 16 Click-to-Run Extensibility Component».
Java usa varios GUID que comienzan con CAFEEFAC.
En la tabla de particiones GUID del esquema de particionado GPT, las particiones BIOS Boot usan el GUID especial 21686148-6449-6E6F-744E-656564454649, que no sigue la definición de GUID; en su lugar, se forma utilizando los códigos ASCII de la cadena Hah!IdontNeedEFI parcialmente en orden little endian.
Valor de depuración
Los valores mágicos de depuración son valores concretos que se escriben en la memoria durante la asignación o la liberación, de modo que más tarde sea posible saber si se han corrompido o no, y para que resulte evidente cuándo se están usando valores tomados de memoria sin inicializar. La memoria se suele visualizar en hexadecimal, por lo que son habituales los valores repetitivos memorables o los valores en hexspeak. Pueden preferirse los valores numéricamente impares para que los procesadores sin direccionamiento por bytes fallen al intentar usarlos como punteros (que deben situarse en direcciones pares). Conviene elegir valores que estén alejados de las direcciones probables (el código del programa, los datos estáticos, los datos del montón o la pila). De forma similar, pueden elegirse de modo que no sean códigos válidos en el conjunto de instrucciones de la arquitectura dada.
Dado que es muy improbable, aunque posible, que un entero de 32 bits adopte este valor concreto, la aparición de un número así en un depurador o un volcado de memoria indica con toda probabilidad un error como un desbordamiento de búfer o una variable sin inicializar.
Entre los ejemplos famosos y habituales se incluyen:
| Código | Descripción |
|---|---|
00008123 |
Se usa en MS Visual C++. Los punteros eliminados se establecen en este valor, de modo que lanzan una excepción cuando se usan después; es un alias más reconocible de la dirección cero. Se activa con la opción Security Development Lifecycle (/sdl). |
..FACADE |
"Facade", usado por varios RTOS. |
1BADB002 |
"1 bad boot", número mágico de la cabecera Multiboot. |
8BADF00D |
"Ate bad food", indica que una aplicación de iOS de Apple ha sido finalizada porque se produjo un tiempo de espera agotado del watchdog. |
A5A5A5A5 |
Se usa en el desarrollo embebido porque el patrón de bits alterno (1010 0101) crea un patrón fácilmente reconocible en los osciloscopios y los analizadores lógicos. |
A5 |
Se usa en el malloc(3) PHK de FreeBSD para depuración cuando /etc/malloc.conf está enlazado simbólicamente a "-J", para inicializar con este valor toda la memoria recién asignada, ya que no es un puntero NULL ni el carácter NUL de ASCII. |
ABABABAB |
Lo usa el HeapAlloc() de depuración de Microsoft para marcar los bytes de guarda de «tierra de nadie» después de la memoria de montón asignada. |
ABADBABE |
"A bad babe", lo usa Apple como número mágico del «Boot Zero Block». |
ABBABABE |
"ABBA babe", lo usa el montón de memoria de Driver: Parallel Lines. |
ABADCAFE |
"A bad cafe", se usa para inicializar toda la memoria no asignada (Mungwall, AmigaOS). |
B16B00B5 |
"Big Boobs", antiguamente lo requería el hipervisor Hyper-V de Microsoft para que los invitados Linux lo usaran como la mitad superior de su «guest id». |
BAADF00D |
"Bad food", lo usa el HeapAlloc() de depuración de Microsoft para marcar la memoria de montón asignada y sin inicializar. |
BAAAAAAD |
"Baaaaaad", indica que el registro de iOS de Apple es una instantánea de pila (stackshot) de todo el sistema, no un informe de fallos. |
BAD22222 |
"Bad too repeatedly", indica que una aplicación VoIP de iOS de Apple ha sido finalizada porque se reanudaba con demasiada frecuencia. |
BADBADBADBAD |
"Bad bad bad bad", memoria «sin inicializar» de los Burroughs Large Systems (palabras de 48 bits). |
BADC0FFEE0DDF00D |
"Bad coffee odd food", se usa en los sistemas RS/6000 de 64 bits de IBM para indicar registros de CPU sin inicializar. |
BADDCAFE |
"Bad cafe", en Solaris de Sun Microsystems, marca la memoria del núcleo sin inicializar (KMEM_UNINITIALIZED_PATTERN). |
BBADBEEF |
"Bad beef", se usa en WebKit para errores especialmente irrecuperables. |
BEBEBEBE |
Lo usa AddressSanitizer para rellenar la memoria asignada pero no inicializada. |
BEEFCACE |
"Beef cake", lo usa Microsoft .NET como número mágico en los archivos de recursos. |
C00010FF |
"Cool off", indica que el sistema operativo cerró una aplicación de iOS de Apple en respuesta a un evento térmico. |
CAFEBABE |
"Cafe babe", lo usa Java para los archivos de clase.
Se usa en los binarios Mach-O multiarquitectura. |
CAFED00D |
"Cafe dude", lo usa Java para su compresión pack200. |
CAFEFEED |
"Cafe feed", lo usa el núcleo de depuración de Solaris de Sun Microsystems para marcar la memoria de kmemfree(). |
CCCCCCCC |
Lo usan la biblioteca de tiempo de ejecución de depuración de C++ de Microsoft y muchos entornos DOS para marcar la memoria de pila sin inicializar. CC es el código de operación de la interrupción de punto de interrupción de depuración INT 3 en los procesadores x86.
|
CDCDCDCD |
Lo usa la función malloc() de depuración de C/C++ de Microsoft para marcar la memoria de montón sin inicializar, normalmente devuelta por HeapAlloc.
|
0D15EA5E |
"Zero Disease", se usa como bandera para indicar un arranque normal en las consolas GameCube y Wii. |
DDDDDDDD |
Lo usan el SmartHeap de MicroQuill y la función free() de depuración de C/C++ de Microsoft para marcar la memoria de montón liberada. |
DEAD10CC |
"Dead lock", indica que una aplicación de iOS de Apple ha sido finalizada porque retuvo un recurso del sistema mientras se ejecutaba en segundo plano. |
DEADBABE |
"Dead babe", se usa al inicio de los archivos de arena (arena) de IRIX de Silicon Graphics. |
DEADBEEF |
"Dead beef", célebremente utilizado en sistemas de IBM como el RS/6000, también usado en los sistemas operativos Mac OS clásico, OPENSTEP Enterprise y el Amiga de Commodore. En Solaris de Sun Microsystems, marca la memoria del núcleo liberada (KMEM_FREE_PATTERN). |
DEADCAFE |
"Dead cafe", lo usa Microsoft .NET como número de error en las DLL. |
DEADC0DE |
"Dead code", se usa como marcador en el firmware de OpenWRT para indicar el comienzo del sistema de archivos jffs2 que se va a crear al final del firmware estático. |
DEADFA11 |
"Dead fail", indica que el usuario ha forzado el cierre de una aplicación de iOS de Apple. |
DEADF00D |
"Dead food", lo usa Mungwall en el Amiga de Commodore para marcar la memoria asignada pero sin inicializar. |
DEFEC8ED |
"Defecated", se usa para los volcados de memoria de OpenSolaris. |
DEADDEAD |
"Dead Dead", indica que el usuario inició deliberadamente un volcado de fallos, ya sea desde el depurador del núcleo o desde el teclado, en Microsoft Windows. |
D00D2BAD
|
"Dude, Too Bad", se usa en los fallos de Safari en macOS Big Sur. |
D00DF33D
|
"Dude feed", lo usa el devicetree para marcar el inicio de las cabeceras. |
EBEBEBEB |
Del SmartHeap de MicroQuill. |
FADEDEAD |
"Fade dead", aparece al final para identificar cada script de AppleScript. |
FDFDFDFD |
Lo usa la función malloc() de depuración de C/C++ de Microsoft para marcar los bytes de guarda de «tierra de nadie» antes y después de la memoria de montón asignada, y algunas funciones de depuración del Secure C-Runtime implementadas por Microsoft (p. ej., strncat_s). |
FEE1DEAD |
"Feel dead", lo usa la llamada al sistema reboot() de Linux. |
FEEDFACE |
"Feed face", aparece en los binarios Mach-O en la plataforma Mac OSX de Apple Inc. En Solaris de Sun Microsystems, marca la zona roja (KMEM_REDZONE_PATTERN).
Lo usan el reproductor VLC y algunas cámaras IP en el protocolo RTP/RTCP; el reproductor VLC envía cuatro bytes en el orden del endianness del sistema. Algunas cámaras IP esperan que el reproductor envíe este número mágico y no inician la transmisión si no lo reciben. |
FEEEFEEE |
"Fee fee", lo usa el HeapFree() de depuración de Microsoft para marcar la memoria de montón liberada. Algunos valores internos de contabilidad cercanos también pueden tener la palabra alta establecida en FEEE. |
La mayoría de estos tienen 32 bits de longitud – el tamaño de palabra de la mayoría de los ordenadores de arquitectura de 32 bits.
La prevalencia de estos valores en la tecnología de Microsoft no es casualidad; se analizan en detalle en el libro de Steve Maguire Writing Solid Code de Microsoft Press. Ofrece diversos criterios para estos valores, como:
- No deberían ser útiles; es decir, cabe esperar que la mayoría de los algoritmos que operan sobre ellos hagan algo inusual. Números como el cero no cumplen este criterio.
- El programador debería poder reconocerlos con facilidad como valores no válidos en el depurador.
- En las máquinas que no tienen alineación de bytes, deberían ser números impares, de modo que desreferenciarlos como direcciones provoque una excepción.
- Deberían provocar una excepción, o quizá incluso una parada del depurador, si se ejecutan como código.
Dado que a menudo se usaban para marcar zonas de memoria que estaban esencialmente vacías, algunos de estos términos pasaron a usarse en expresiones que significan «desaparecido, abortado, expulsado de la memoria»; p. ej., «Your program is DEADBEEF» (tu programa está DEADBEEF).