Nombre magique (programmation).
Valeur numérique dont la signification n'est pas claire
En programmation informatique, un nombre magique ou une signature de fichier est un littéral numérique présent dans le code source et dont la signification particulière n'est pas évidente pour le lecteur. En informatique de manière générale, et pas seulement en programmation, le terme désigne aussi un nombre qui identifie un concept précis mais dont le sens reste obscur sans connaissance supplémentaire. Par exemple, certains formats de fichier sont identifiés par un nombre magique intégré au fichier ). De même, un nombre associé de façon relativement unique à un concept particulier, tel qu'un identifiant unique universel, peut être qualifié de nombre magique.
Littéral numérique
Un nombre magique ou une constante magique est un littéral numérique présent dans le code source et dont la signification particulière n'est pas évidente dans son contexte. Cela est considéré comme un anti-modèle et enfreint l'une des plus anciennes règles de la programmation, qui remonte aux manuels de COBOL, FORTRAN et PL/1 des années 1960.
Par exemple, dans le code suivant qui calcule un prix après taxe, 1.05 est un nombre magique car cette valeur encode le taux de taxe sur les ventes, 5 %, d'une manière qui n'a rien d'évident.
price_after_tax = 1.05 * price
L'utilisation de nombres magiques dans le code masque l'intention des développeurs ayant choisi ce nombre, multiplie les occasions d'erreurs subtiles et rend plus difficile l'adaptation et l'extension du programme par la suite. Par exemple, il est difficile de dire si chaque chiffre de 3.14159265358979323846 est correctement saisi, ou si cette constante représentant pi peut être tronquée à 3.14159 sans nuire au fonctionnement du programme malgré sa précision réduite. Remplacer tous les nombres magiques significatifs par des constantes nommées (aussi appelées variables explicatives) rend les programmes plus faciles à lire, à comprendre et à maintenir.
L'exemple ci-dessus peut être amélioré en ajoutant une variable au nom descriptif :
TAX = 0.05 price_after_tax = (1.0 + TAX) * price
Un bon nom peut produire un code plus facile à comprendre pour un mainteneur qui n'est pas l'auteur d'origine, voire pour l'auteur d'origine après un certain temps. Un exemple de constante au nom peu informatif est int SIXTEEN = 16, tandis que int NUMBER_OF_BITS = 16 serait sans doute plus utile.
Les données non numériques peuvent posséder les mêmes propriétés magiques, et donc présenter les mêmes problèmes que les nombres magiques. Ainsi, déclarer const string testUserName = "John" et utiliser testUserName peut être préférable à l'utilisation directe du littéral "John".
Exemple
Par exemple, s'il faut mélanger aléatoirement les valeurs d'un tableau représentant un jeu standard de cartes à jouer, ce pseudo-code remplit la tâche à l'aide de l'algorithme de mélange de Fisher-Yates :
for i from 1 to 52
j := i + randomInt(53 - i) - 1
a.swapEntries(i, j)
où a est un objet tableau, la fonction randomInt(x) choisit un entier aléatoire compris entre 1 et x inclus, et swapEntries(i, j) échange les i-ième et j-ième entrées du tableau. Dans l'exemple précédent, 52 et 53 sont des nombres magiques, dont le lien mutuel n'est d'ailleurs pas clair. Il est considéré comme un meilleur style de programmation d'écrire ce qui suit :
int deckSize:= 52
for i from 1 to deckSize
j := i + randomInt(deckSize + 1 - i) - 1
a.swapEntries(i, j)
Cette forme est préférable pour plusieurs raisons :
- Meilleure lisibilité. Un programmeur qui lit le premier exemple peut se demander : Que signifie le nombre 52 ici ? Pourquoi 52 ? Le programmeur peut en déduire le sens après une lecture attentive du code, mais ce n'est pas évident. Les nombres magiques deviennent particulièrement déroutants lorsque le même nombre est utilisé à des fins différentes dans une même portion de code.
- Plus facile à maintenir. Il est plus simple de modifier la valeur du nombre, car elle n'est pas dupliquée. Modifier la valeur d'un nombre magique est source d'erreurs, car la même valeur est souvent utilisée plusieurs fois à différents endroits d'un programme. De plus, lorsque deux variables ou nombres sémantiquement distincts ont la même valeur, ils peuvent être accidentellement modifiés ensemble. Pour adapter le premier exemple afin de mélanger un jeu de Tarot, qui comporte 78 cartes, un programmeur pourrait naïvement remplacer chaque occurrence de 52 dans le programme par 78. Cela poserait deux problèmes. Premièrement, on manquerait la valeur 53 à la deuxième ligne de l'exemple, ce qui ferait échouer l'algorithme d'une manière subtile. Deuxièmement, on remplacerait probablement les caractères « 52 » partout, qu'ils se rapportent ou non à la taille du jeu ou à tout autre chose, comme le nombre de semaines dans une année du calendrier grégorien, ou plus insidieusement qu'ils fassent partie d'un nombre comme « 1523 », ce qui introduirait des bogues. À l'inverse, modifier la valeur de la variable
deckSizedans le second exemple serait un changement simple, sur une seule ligne. - Encourage la documentation. L'endroit unique où la variable nommée est déclarée constitue un bon emplacement pour documenter ce que la valeur signifie et pourquoi elle a cette valeur. Avoir la même valeur dans une multitude d'endroits conduit soit à des commentaires en double (avec les problèmes qui en découlent lorsqu'on en met à jour certains en en oubliant d'autres), soit à l'absence d'un endroit unique où il soit à la fois naturel pour l'auteur d'expliquer la valeur et probable que le lecteur cherche une explication.
- Regroupe l'information. Les déclarations des variables de type « nombre magique » peuvent être placées ensemble, généralement en tête d'une fonction ou d'un fichier, ce qui facilite leur examen et leur modification.
- Détecte les fautes de frappe. Utiliser une variable (plutôt qu'un littéral) tire parti des vérifications du compilateur. Taper accidentellement « 62 » au lieu de « 52 » passerait inaperçu, tandis que taper «
dekSize» au lieu de «deckSize» entraînerait un avertissement du compilateur indiquant quedekSizen'est pas déclaré. - Réduit la saisie. Si un EDI prend en charge la complétion de code, il complétera la majeure partie du nom de la variable à partir de ses premières lettres.
- Facilite le paramétrage. Par exemple, pour généraliser l'exemple ci-dessus en une procédure qui mélange un jeu d'un nombre quelconque de cartes, il suffirait de transformer
deckSizeen paramètre de cette procédure, alors que le premier exemple nécessiterait plusieurs modifications.
function shuffle (int deckSize)
for i from 1 to deckSize
j := i + randomInt(deckSize + 1 - i) - 1
a.swapEntries(i, j)
Les inconvénients sont les suivants :
- Rompt la localité. Lorsque la constante nommée n'est pas définie près de son utilisation, cela nuit à la localité, et donc à la compréhensibilité, du code. Placer le 52 à un endroit éventuellement éloigné signifie que, pour comprendre entièrement le fonctionnement de la boucle « for » (par exemple pour estimer le temps d'exécution de la boucle), il faut retrouver la définition et vérifier qu'il s'agit bien du nombre attendu. Cela est facile à éviter (en rapprochant la déclaration) lorsque la constante n'est utilisée que dans une seule portion du code. En revanche, lorsque la constante nommée est utilisée dans des portions disparates, l'emplacement distant signale au lecteur que la même valeur apparaît à d'autres endroits du code, qui méritent peut-être aussi un coup d'œil.
- Augmente la verbosité. La déclaration de la constante ajoute une ligne. Lorsque le nom de la constante est plus long que la valeur, en particulier si plusieurs constantes de ce type apparaissent sur une même ligne, cela peut rendre nécessaire le fractionnement d'une instruction logique du code sur plusieurs lignes. Une augmentation de la verbosité peut se justifier lorsqu'il existe un risque de confusion au sujet de la constante, ou lorsqu'il est probable que la constante doive être modifiée, comme la réutilisation d'une routine de mélange pour d'autres jeux de cartes. Elle peut tout autant se justifier comme un gain d'expressivité.
- Considérations de performance. Il peut être plus lent d'évaluer l'expression
deckSize + 1à l'exécution que la valeur « 53 ». Cela dit, la plupart des compilateurs modernes recourent à des techniques telles que le repliement de constantes et l'optimisation de boucle pour résoudre l'addition lors de la compilation, de sorte qu'il n'y a généralement aucune ou qu'une pénalité de vitesse négligeable par rapport à l'utilisation de nombres magiques dans le code. Le coût du débogage et le temps nécessaire pour tenter de comprendre un code non explicite doivent en particulier être mis en balance avec le coût de calcul infime.
Usage admis
Lorsqu'un littéral numérique n'a pas de signification particulière, son utilisation n'est pas qualifiée de magique, même si ce qui constitue une signification « particulière » reste subjectif. Parmi les littéraux qui ne sont souvent pas considérés comme magiques figurent :
- L'utilisation de 0 et de 1 comme valeurs initiales ou d'incrément dans une boucle for, comme dans
for (int i = 0; i < max; i += 1)
- L'utilisation de 2 pour vérifier si un nombre est pair ou impair, comme dans
isEven = (x % 2 == 0), où%est l'opérateur modulo
- L'utilisation de littéraux simples, par exemple dans des expressions telles que
circumference = 2 * Math.PI * radius, ou pour calculer le discriminant d'une équation du second degré sous la formed = b^2 − 4*a*c
- L'utilisation de puissances de 10 pour convertir des valeurs métriques (par exemple entre grammes et kilogrammes) ou pour calculer des pourcentages et des valeurs en pour mille
- Les exposants dans des expressions telles que
(f(x) ** 2 + f(y) ** 2) ** 0.5pour
- Les littéraux 1 et 0 sont parfois utilisés pour représenter les valeurs booléennes vrai et faux. On pourrait soutenir qu'attribuer ces valeurs à des noms tels que TRUE et FALSE serait préférable.
- En C et C++, 0 est souvent utilisé pour signifier pointeur nul, même si la bibliothèque standard du C définit une macro
NULLet que le C++ moderne comprend un mot-clénullptr.
Indicateur de format
Origine
Les indicateurs de format ont d'abord été utilisés dans le code source des premières versions d'Unix Version 7.
Unix a été porté sur l'un des premiers PDP-11/20 de DEC, qui ne disposait pas de protection de la mémoire. Aussi les premières versions d'Unix utilisaient-elles le modèle de référence mémoire relogeable. Les versions d'Unix antérieures à la Sixth Edition lisaient un fichier exécutable en mémoire et sautaient à la première adresse mémoire basse du programme, l'adresse relative zéro. Avec le développement de versions d'Unix à pagination, un en-tête fut créé pour décrire les composants de l'image exécutable. De plus, une instruction de branchement fut insérée comme premier mot de l'en-tête afin de sauter l'en-tête et de démarrer le programme. De cette façon, un programme pouvait s'exécuter dans l'ancien mode (ordinaire) de référence mémoire relogeable ou en mode paginé. À mesure que de nouveaux formats exécutables étaient développés, de nouvelles constantes étaient ajoutées en incrémentant le décalage de branchement.
Dans le code source de la Sixth Edition du chargeur de programmes Unix, la fonction exec() lisait l'image exécutable (binaire) depuis le système de fichiers. Les 8 premiers octets du fichier formaient un en-tête contenant les tailles des zones de programme (texte) et de données initialisées (globales). De plus, le premier mot de 16 bits de l'en-tête était comparé à deux constantes afin de déterminer si l'image exécutable contenait des références mémoire relogeables (normale), la nouvelle image exécutable paginée en lecture seule, ou l'image paginée à instructions et données séparées. Il n'était pas fait mention du double rôle de la constante d'en-tête, mais l'octet de poids fort de la constante était en réalité le code d'opération de l'instruction de branchement du PDP-11 (octal 000407 ou hexadécimal 0107). En ajoutant sept au compteur de programme, on constatait que si cette constante était exécutée, elle faisait sauter le service exec() d'Unix par-dessus l'en-tête de huit octets de l'image exécutable et démarrait le programme.
Comme les Sixth et Seventh Editions d'Unix employaient du code de pagination, le double rôle de la constante d'en-tête était masqué. C'est-à-dire que le service exec() lisait les (méta)données de l'en-tête du fichier exécutable dans un tampon de l'espace noyau, mais lisait l'image exécutable dans l'espace utilisateur, n'utilisant ainsi pas la fonction de branchement de la constante. La création des nombres magiques fut implémentée dans l'éditeur de liens et le chargeur Unix, et le branchement par nombre magique était probablement encore utilisé dans l'ensemble des programmes de diagnostic autonomes livrés avec les Sixth et Seventh Editions. Ainsi, la constante d'en-tête créait bel et bien une illusion et répondait aux critères du magique.
Dans Unix Version Seven, la constante d'en-tête n'était pas testée directement, mais affectée à une variable nommée ux_mag puis désignée par la suite comme le nombre magique. Probablement en raison de son caractère unique, le terme nombre magique en vint à désigner le type de format exécutable, puis s'étendit pour désigner le type de système de fichiers, et s'étendit de nouveau pour désigner tout type de fichier.
Dans les fichiers
Les nombres magiques sont courants dans les programmes de nombreux systèmes d'exploitation. Les nombres magiques implémentent des données fortement typées et constituent une forme de signalisation dans la bande à destination du programme de contrôle qui lit le ou les types de données lors de l'exécution. De nombreux fichiers comportent de telles constantes qui identifient les données contenues. Détecter ces constantes dans les fichiers est un moyen simple et efficace de distinguer de nombreux formats de fichier et peut fournir des informations supplémentaires à l'exécution.
- Exemples
- Les fichiers de classe Java compilés (bytecode) et les binaires Mach-O commencent par l'hexadécimal
CA FE BA BE. Lorsqu'ils sont compressés avec Pack200, les octets deviennentCA FE D0 0D. - Les fichiers image GIF contiennent le code ASCII de « GIF89a » (
47 49 46 38 39 61) ou « GIF87a » (47 49 46 38 37 61) - Les fichiers image JPEG commencent par
FF D8et se terminent parFF D9. Les fichiers JPEG/JFIF contiennent la chaîne terminée par un caractère nul « JFIF » (4A 46 49 46 00). Les fichiers JPEG/Exif contiennent la chaîne terminée par un caractère nul « Exif » (45 78 69 66 00), suivie d'autres métadonnées concernant le fichier. - Les fichiers image PNG commencent par une signature de 8 octets qui identifie le fichier comme un fichier PNG et permet de détecter les problèmes de transfert de fichier courants : « \211PNG\r\n\032\n » (
89 50 4E 47 0D 0A 1A 0A). Cette signature contient divers caractères de saut de ligne afin de permettre la détection de conversions automatiques de sauts de ligne non souhaitées, comme le transfert du fichier par FTP en mode de transfert ASCII au lieu du mode binaire. - Les fichiers audio MIDI standard contiennent le code ASCII de « MThd » (MIDI Track header,
4D 54 68 64) suivi d'autres métadonnées. - Les scripts Unix ou Linux peuvent commencer par un shebang (« #! »,
23 21) suivi du chemin vers un interpréteur, si l'interpréteur est susceptible d'être différent de celui depuis lequel le script a été invoqué. - Les exécutables ELF commencent par l'octet
7Fsuivi de « ELF » (7F 45 4C 46). - Les fichiers et programmes PostScript commencent par « %! » (
25 21). - Les fichiers PDF commencent par « %PDF » (hexadécimal
25 50 44 46). - Les fichiers exécutables DOS MZ et le stub EXE des fichiers PE (Portable Executable) de Microsoft Windows commencent par les caractères « MZ » (
4D 5A), les initiales du concepteur du format de fichier, Mark Zbikowski. La définition autorise également le rare « ZM » (5A 4D) pour dosZMXP, un EXE non PE. - Le format de superbloc du Berkeley Fast File System est identifié soit par
19 54 01 19, soit par01 19 54selon la version ; les deux représentent la date de naissance de l'auteur, Marshall Kirk McKusick. - Le Master Boot Record des périphériques de stockage amorçables de presque tous les compatibles PC IBM IA-32 a pour deux derniers octets le code
55 AA. - Les exécutables des consoles de jeux vidéo portables Game Boy et Game Boy Advance comportent respectivement un nombre magique de 48 ou 156 octets, à un emplacement fixe de l'en-tête. Ce nombre magique encode une image bitmap du logo Nintendo.
- Les fichiers exécutables Hunk des logiciels Amiga s'exécutant sur les machines Amiga classiques à base de 68000 commençaient tous par le nombre hexadécimal $000003f3, surnommé le « Magic Cookie ».
- Sur l'Amiga, la seule adresse absolue du système est l'hexadécimal $0000 0004 (emplacement mémoire 4), qui contient l'emplacement de départ appelé SysBase, un pointeur vers exec.library, le « noyau » de l'Amiga.
- Les fichiers PEF, utilisés par le Mac OS classique et BeOS pour les exécutables PowerPC, contiennent le code ASCII de « Joy! » (
4A 6F 79 21) en préfixe. - Les fichiers TIFF commencent soit par « II », soit par « MM » suivi de 42 sous forme d'entier de deux octets en ordre petit-boutiste ou gros-boutiste. « II » correspond à Intel, qui utilise l'ordre petit-boutiste, de sorte que le nombre magique est
49 49 2A 00. « MM » correspond à Motorola, qui utilise l'ordre gros-boutiste, de sorte que le nombre magique est4D 4D 00 2A. - Les fichiers texte Unicode encodés en UTF-16 commencent souvent par la marque d'ordre des octets pour détecter le boutisme (
FE FFpour le gros-boutiste etFF FEpour le petit-boutiste). Et sous Microsoft Windows, les fichiers texte UTF-8 commencent souvent par l'encodage UTF-8 du même caractère,EF BB BF. - Les fichiers Bitcode LLVM commencent par « BC » (
42 43). - Les fichiers WAD commencent par « IWAD » ou « PWAD » (pour Doom), « WAD2 » (pour Quake) et « WAD3 » (pour Half-Life).
- Les fichiers Microsoft Compound File Binary Format (surtout connu comme l'un des anciens formats des documents Microsoft Office) commencent par
D0 CF 11 E0, qui évoque visuellement le mot « DOCFILE0 ». - Les en-têtes des fichiers ZIP apparaissent souvent dans les éditeurs de texte sous la forme « PK♥♦ » (
50 4B 03 04), où « PK » sont les initiales de Phil Katz, auteur de l'utilitaire de compression DOS PKZIP. - Les en-têtes des fichiers 7z commencent par « 7z » (nombre magique complet :
37 7A BC AF 27 1C).
- Détection
L'utilitaire Unix file peut lire et interpréter les nombres magiques des fichiers, et le fichier utilisé pour analyser cette information s'appelle magic. L'utilitaire Windows TrID a un objectif similaire.
Dans les protocoles
- Exemples
- Le protocole OSCAR, utilisé dans AIM/ICQ, préfixe les requêtes par
2A. - Dans le protocole RFB utilisé par VNC, un client entame sa conversation avec un serveur en envoyant « RFB » (
52 46 42, pour « Remote Frame Buffer ») suivi du numéro de version de protocole du client. - Dans le protocole SMB utilisé par Microsoft Windows, chaque requête SMB ou réponse du serveur commence par
FF 53 4D 42, soit\xFFSMBau début de la requête SMB. - Dans le protocole MSRPC utilisé par Microsoft Windows, chaque requête fondée sur TCP commence par
05en début de requête (représentant Microsoft DCE/RPC Version 5), immédiatement suivi d'un00ou01pour la version mineure. Dans les requêtes MSRPC fondées sur UDP, le premier octet est toujours04. - Dans les interfaces COM et DCOM marshalées, appelées OBJREF, la séquence d'octets « MEOW » (
4D 45 4F 57) figure toujours en début. Les extensions de débogage (utilisées pour le détournement de canal DCOM) sont précédées de la séquence d'octets « MARB » (4D 41 52 42). - Les requêtes non chiffrées d'un tracker BitTorrent commencent par un seul octet contenant la valeur
19représentant la longueur de l'en-tête, immédiatement suivi de l'expression « BitTorrent protocol » à la position d'octet 1. - Le trafic eDonkey2000/eMule commence par un seul octet représentant la version du client. Actuellement,
E3représente un client eDonkey,C5représente eMule etD4représente eMule compressé. - Les 4 premiers octets d'un bloc dans la chaîne de blocs Bitcoin contiennent un nombre magique qui sert d'identifiant de réseau. La valeur
D9 B4 BE F9indique le réseau principal, tandis queDA B5 BF FAindique le testnet. - Les transactions SSL commencent toujours par un message « client hello ». Le schéma d'encapsulation des enregistrements utilisé pour préfixer tous les paquets SSL comprend des formes d'en-tête de deux et trois octets. Généralement, un message « client hello » SSL version 2 est préfixé par un
80, et une réponse de serveur SSLv3 à un « client hello » commence par16(bien que cela puisse varier). - Les paquets DHCP utilisent une valeur « magic cookie » de
63 82 53 63au début de la section des options du paquet. Cette valeur est incluse dans tous les types de paquets DHCP. - Les connexions HTTP/2 commencent par la chaîne de 24 caractères
PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n. Elle est conçue pour éviter le traitement des trames par les serveurs et intermédiaires qui prennent en charge des versions antérieures de HTTP mais pas la 2.0. - La poignée de main d'ouverture WebSocket utilise une chaîne contenant l'UUIDv4
258EAFA5-E914-47DA-95CA-C5AB0DC85B11.
Dans les interfaces
Les nombres magiques sont courants dans les fonctions d'API et les interfaces de nombreux systèmes d'exploitation, dont DOS, Windows et NetWare :
- Exemples
- Les BIOS des compatibles IBM PC utilisent les valeurs magiques
00 00et12 34pour décider si le système doit ou non recompter la mémoire au redémarrage, réalisant ainsi un démarrage à froid ou à chaud. Ces valeurs sont également utilisées par les gestionnaires de mémoire EMM386 qui interceptent les demandes de démarrage. Les BIOS utilisent aussi la valeur magique55 AApour déterminer si un disque est amorçable. - Le cache disque SMARTDRV de MS-DOS (nom de code « Bambi ») utilise les valeurs magiques
BA BEetEB ABdans ses fonctions d'API. - De nombreux pilotes DR-DOS, Novell DOS et OpenDOS développés dans l'ancien European Development Centre au Royaume-Uni utilisent la valeur
0E DCcomme jeton magique lorsqu'ils invoquent ou fournissent des fonctionnalités supplémentaires reposant sur les fonctions DOS standard (émulées), NWCACHE en étant un exemple.
Autres usages
- Exemples
- L'adresse MAC par défaut des SoC Texas Instruments est
DE:AD:BE:EF:00:00.
GUID
Il est possible de créer ou de modifier des identifiants uniques globaux (GUID) de manière à les rendre mémorisables, mais cela est fortement déconseillé car cela compromet leur robustesse en tant qu'identifiants quasi uniques. Les spécifications de génération des GUID et des UUID sont assez complexes, ce qui les rend pratiquement uniques s'ils sont correctement implémentés.
Les numéros d'identification de produit Microsoft Windows pour les produits Microsoft Office se terminent parfois par 0000-0000-0000000FF1CE (« OFFICE »), comme 90160000-008C-0000-0000-0000000FF1CE, l'identifiant de produit du « Office 16 Click-to-Run Extensibility Component ».
Java utilise plusieurs GUID commençant par CAFEEFAC.
Dans la table de partitionnement GUID du schéma de partitionnement GPT, les partitions BIOS Boot utilisent le GUID spécial 21686148-6449-6E6F-744E-656564454649, qui ne respecte pas la définition d'un GUID ; il est plutôt formé à partir des codes ASCII de la chaîne Hah!IdontNeedEFI, en partie en ordre petit-boutiste.
Valeur de débogage
Les valeurs magiques de débogage sont des valeurs spécifiques écrites en mémoire lors de l'allocation ou de la libération, afin qu'il soit possible par la suite de déterminer si elles ont été corrompues, et de rendre évidente l'utilisation de valeurs provenant de mémoire non initialisée. La mémoire est généralement examinée en hexadécimal, c'est pourquoi des valeurs mémorisables, répétitives ou en hexspeak sont courantes. Des valeurs numériquement impaires peuvent être préférées afin que les processeurs sans adressage par octet provoquent une erreur lorsqu'on tente de les utiliser comme pointeurs (qui doivent se situer à des adresses paires). On choisira des valeurs éloignées des adresses probables (le code du programme, les données statiques, les données du tas ou la pile). De même, elles peuvent être choisies pour ne pas être des codes valides dans le jeu d'instructions de l'architecture donnée.
Comme il est très improbable, quoique possible, qu'un entier 32 bits prenne cette valeur précise, l'apparition d'un tel nombre dans un débogueur ou un vidage mémoire indique très probablement une erreur telle qu'un dépassement de tampon ou une variable non initialisée.
Parmi les exemples célèbres et courants figurent :
| Code | Description |
|---|---|
00008123 |
Utilisé dans MS Visual C++. Les pointeurs supprimés prennent cette valeur, de sorte qu'ils déclenchent une exception lorsqu'ils sont utilisés ensuite ; c'est un alias plus reconnaissable de l'adresse zéro. Il est activé par l'option Security Development Lifecycle (/sdl). |
..FACADE |
« Facade » (façade), utilisé par plusieurs RTOS. |
1BADB002 |
« 1 bad boot » (un mauvais démarrage), nombre magique de l'en-tête Multiboot. |
8BADF00D |
« Ate bad food » (a mangé de la mauvaise nourriture), indique qu'une application iOS d'Apple a été interrompue parce qu'un délai de surveillance (watchdog) a expiré. |
A5A5A5A5 |
Utilisé dans le développement embarqué car le motif de bits alterné (1010 0101) crée un schéma facilement reconnaissable sur les oscilloscopes et les analyseurs logiques. |
A5 |
Utilisé dans le malloc(3) PHK de FreeBSD pour le débogage lorsque /etc/malloc.conf pointe par lien symbolique vers « -J », afin d'initialiser toute la mémoire nouvellement allouée, cette valeur n'étant ni un pointeur NULL ni le caractère NUL ASCII. |
ABABABAB |
Utilisé par le HeapAlloc() de débogage de Microsoft pour marquer les octets de garde du « no man's land » situé après la mémoire de tas allouée. |
ABADBABE |
« A bad babe » (une mauvaise nana), utilisé par Apple comme nombre magique du « Boot Zero Block ». |
ABBABABE |
« ABBA babe » (nana d'ABBA), utilisé par le tas mémoire de Driver: Parallel Lines. |
ABADCAFE |
« A bad cafe » (un mauvais café), utilisé pour initialiser toute la mémoire non allouée (Mungwall, AmigaOS). |
B16B00B5 |
« Big Boobs » (gros nichons), autrefois exigé par l'hyperviseur Hyper-V de Microsoft pour être utilisé par les invités Linux comme moitié supérieure de leur « guest id ». |
BAADF00D |
« Bad food » (mauvaise nourriture), utilisé par le HeapAlloc() de débogage de Microsoft pour marquer la mémoire de tas allouée mais non initialisée. |
BAAAAAAD |
« Baaaaaad » (mauvais), indique que le journal iOS d'Apple est un instantané de pile (stackshot) de l'ensemble du système, et non un rapport de plantage. |
BAD22222 |
« Bad too repeatedly » (mauvais, trop souvent), indique qu'une application VoIP iOS d'Apple a été interrompue parce qu'elle reprenait trop fréquemment. |
BADBADBADBAD |
« Bad bad bad bad » (mauvais mauvais mauvais mauvais), mémoire « non initialisée » des Burroughs Large Systems (mots de 48 bits). |
BADC0FFEE0DDF00D |
« Bad coffee odd food » (mauvais café, nourriture bizarre), utilisé sur les systèmes 64 bits RS/6000 d'IBM pour indiquer des registres de processeur non initialisés. |
BADDCAFE |
« Bad cafe » (mauvais café), sur Solaris de Sun Microsystems, marque la mémoire noyau non initialisée (KMEM_UNINITIALIZED_PATTERN). |
BBADBEEF |
« Bad beef » (mauvais bœuf), utilisé dans WebKit pour les erreurs particulièrement irrécupérables. |
BEBEBEBE |
Utilisé par AddressSanitizer pour remplir la mémoire allouée mais non initialisée. |
BEEFCACE |
« Beef cake », utilisé par Microsoft .NET comme nombre magique dans les fichiers de ressources. |
C00010FF |
« Cool off » (refroidir), indique qu'une application iOS d'Apple a été interrompue par le système d'exploitation en réponse à un événement thermique. |
CAFEBABE |
« Cafe babe » (nana du café), utilisé par Java pour les fichiers de classe.
Utilisé dans les binaires Mach-O multi-architectures. |
CAFED00D |
« Cafe dude » (mec du café), utilisé par Java pour sa compression pack200. |
CAFEFEED |
« Cafe feed », utilisé par le noyau de débogage Solaris de Sun Microsystems pour marquer la mémoire de kmemfree(). |
CCCCCCCC |
Utilisé par la bibliothèque d'exécution de débogage C++ de Microsoft et de nombreux environnements DOS pour marquer la mémoire de pile non initialisée. CC est le code d'opération de l'interruption de point d'arrêt de débogage INT 3 sur les processeurs x86.
|
CDCDCDCD |
Utilisé par la fonction de débogage malloc() C/C++ de Microsoft pour marquer la mémoire de tas non initialisée, généralement renvoyée par HeapAlloc.
|
0D15EA5E |
« Zero Disease » (zéro maladie), utilisé comme drapeau pour indiquer un démarrage normal sur les consoles GameCube et Wii. |
DDDDDDDD |
Utilisé par SmartHeap de MicroQuill et la fonction de débogage free() C/C++ de Microsoft pour marquer la mémoire de tas libérée. |
DEAD10CC |
« Dead lock » (interblocage), indique qu'une application iOS d'Apple a été interrompue parce qu'elle conservait une ressource système alors qu'elle s'exécutait en arrière-plan. |
DEADBABE |
« Dead babe » (nana morte), utilisé au début des fichiers d'arène IRIX de Silicon Graphics. |
DEADBEEF |
« Dead beef » (bœuf mort), célèbre sur les systèmes IBM tels que le RS/6000, également utilisé dans les Mac OS classiques, systèmes d'exploitation, OPENSTEP Enterprise et l'Amiga de Commodore. Sur Solaris de Sun Microsystems, marque la mémoire noyau libérée (KMEM_FREE_PATTERN). |
DEADCAFE |
« Dead cafe » (café mort), utilisé par Microsoft .NET comme numéro d'erreur dans les DLL. |
DEADC0DE |
« Dead code » (code mort), utilisé comme marqueur dans le micrologiciel OpenWRT pour signaler le début du système de fichiers jffs2 à créer, à la fin du micrologiciel statique. |
DEADFA11 |
« Dead fail » (échec mort), indique qu'une application iOS d'Apple a été forcée à quitter par l'utilisateur. |
DEADF00D |
« Dead food » (nourriture morte), utilisé par Mungwall sur l'Amiga de Commodore pour marquer la mémoire allouée mais non initialisée. |
DEFEC8ED |
« Defecated » (déféqué), utilisé pour les vidages mémoire d'OpenSolaris. |
DEADDEAD |
« Dead Dead » (mort mort) indique que l'utilisateur a délibérément déclenché un vidage de plantage depuis le débogueur noyau ou le clavier sous Microsoft Windows. |
D00D2BAD
|
« Dude, Too Bad » (mec, dommage), utilisé par les plantages de Safari sur macOS Big Sur. |
D00DF33D
|
« Dude feed » (mec, à manger), utilisé par le devicetree pour marquer le début des en-têtes. |
EBEBEBEB |
Provient de SmartHeap de MicroQuill. |
FADEDEAD |
« Fade dead » (s'estompe, mort), figure à la fin pour identifier chaque script AppleScript. |
FDFDFDFD |
Utilisé par la fonction de débogage malloc() C/C++ de Microsoft pour marquer les octets de garde du « no man's land » avant et après la mémoire de tas allouée, ainsi que par certaines fonctions de débogage du Secure C-Runtime implémentées par Microsoft (par exemple strncat_s). |
FEE1DEAD |
« Feel dead » (se sentir mort), utilisé par l'appel système reboot() de Linux. |
FEEDFACE |
« Feed face » (nourrir le visage), observé dans les binaires Mach-O sur la plateforme Mac OSX d'Apple Inc.. Sur Solaris de Sun Microsystems, marque la zone rouge (KMEM_REDZONE_PATTERN).
Utilisé par VLC player et certaines caméras IP dans le protocole RTP/RTCP ; VLC player envoie quatre octets dans l'ordre du boutisme du système. Certaines caméras IP attendent que le lecteur envoie ce nombre magique et ne démarrent pas le flux s'il n'est pas reçu. |
FEEEFEEE |
« Fee fee », utilisé par le HeapFree() de débogage de Microsoft pour marquer la mémoire de tas libérée. Certaines valeurs de comptabilité interne proches peuvent également avoir le mot de poids fort défini à FEEE. |
La plupart de ces valeurs font 32 bits de long – la taille de mot de la plupart des ordinateurs à architecture 32 bits.
La prévalence de ces valeurs dans la technologie Microsoft n'est pas un hasard ; elles sont abordées en détail dans le livre Writing Solid Code de Steve Maguire, publié par Microsoft Press. Il y donne divers critères pour ces valeurs, tels que :
- Elles ne devraient pas être utiles ; c'est-à-dire que la plupart des algorithmes qui les manipulent devraient se comporter de façon inhabituelle. Des nombres comme zéro ne répondent pas à ce critère.
- Elles devraient être facilement reconnues par le programmeur comme des valeurs invalides dans le débogueur.
- Sur les machines sans alignement par octet, elles devraient être des nombres impairs, de sorte que leur déréférencement en tant qu'adresses provoque une exception.
- Elles devraient provoquer une exception, voire un arrêt du débogueur, si elles sont exécutées comme du code.
Comme elles servaient souvent à marquer des zones de mémoire essentiellement vides, certains de ces termes en sont venus à être utilisés dans des expressions signifiant « disparu, abandonné, vidé de la mémoire » ; par exemple « Your program is DEADBEEF » (ton programme est DEADBEEF).