Nella programmazione di computer , il termine numero magico (in francese "numero magico" ) può riferirsi a:
Questo tipo di numero magico è apparso nelle prime versioni del codice sorgente della versione 7 di Unix . Sebbene abbia perso il suo significato originale, il termine è sopravvissuto nel lessico dell'informatica.
Quando Unix è stato portato sul primo DEC PDP-11 /20, non aveva alcun meccanismo per la protezione della memoria e veniva utilizzato per i riferimenti di memoria riallocabili (en) . Quindi, le versioni precedenti Unix versione 6 leggere un file eseguibile dalla memoria saltando a compensare 0. Con lo sviluppo di impaginazione , successive versioni di Unix hanno visto lo sviluppo delle intestazioni che specificano i componenti di un file eseguibile. È stata sviluppata un'istruzione di salto posta all'inizio dell'intestazione per consentire l'esecuzione diretta del programma (senza leggere l'intestazione); che consente di scegliere tra l'esecuzione del programma utilizzando la vecchia modalità utilizzando riferimenti di memoria riallocabili ( modalità normale ) o tramite impaginazione. Con lo sviluppo di formati eseguibili, sono state aggiunte nuove costanti di salto incrementando l'offset.
Nel Commento dei Lions su UNIX 6a Edizione, con codice sorgente (in) Versione 6 Unix, la funzione exec()legge l'immagine binaria di un eseguibile dal file system. I primi otto byte formano l' intestazione che contiene la dimensione del programma (segmento di testo ) e le variabili inizializzate (segmento globale ). La prima parola di sedici bit di questa intestazione viene confrontata con due costanti per determinare se l'eseguibile utilizza riferimenti di memoria riallocabili, il nuovo sistema di pagine di sola lettura o pagine separate per istruzioni e dati. Nella sesta e settima versione di Unix, il doppio ruolo di questa costante all'inizio dell'intestazione non era specificato ma il bit più significativo di questa costante era il codice operativo dell'istruzione di salto su un PDP-11 ( ottale 000407 o esadecimale 0107 ). Se aggiungiamo sette al contatore del programma di un programma eseguito, utilizzerà il servizio exec()per avviarsi.
Il servizio exec()legge l'intestazione del file eseguibile ( meta ) da un buffer dello spazio del kernel ma l'immagine eseguibile viene letta nello spazio utente e quindi senza poter utilizzare la costante di salto. I numeri magici sono stati poi implementati nel linker e loader Unix; avrebbero dovuto essere usati in seguito nei programmi di test forniti con le versioni 6 e 7 di Unix.
Nella versione 7, la costante non viene letta direttamente; viene prima assegnato alla variabile ux_mage successivamente è stato indicato con l'espressione numero magico . Sapendo che allora c'erano in questo Unix circa 10.000 righe di codice e molte costanti usate, questo nome è piuttosto curioso per una costante, almeno quanto il commento lasciato nella parte riguardante il cambio di contesto della versione 6 dalla Gestore di applicazioni Unix. Questo è probabilmente il motivo per cui il termine si riferiva quindi al tipo di eseguibile, quindi esteso ai file system e ulteriormente esteso per riferirsi a un eseguibile che utilizzava una digitazione forte .
Molti di questi numeri sono il risultato di una forte digitazione dei dati o del loro multiplexing . Consentono ai programmi di elaborazione delle informazioni di identificare i seguenti dati e in particolare di distinguere il formato dei dati utilizzato.
EsempiIn unix, il comando viene fileutilizzato per individuare il formato di un file da una firma. Ci sono diversi progetti che tentano di elencarli.
Il termine numero magico può anche riferirsi all'uso di costanti numeriche senza nome nel codice sorgente di un programma. L'uso di queste costanti viola le vecchie regole di programmazione di COBOL , FORTRAN e PL / I , non rende più chiara la scelta di questo valore e generalmente causa errori di programmazione. Secondo alcuni, la denominazione di tutte le costanti rende il codice più leggibile, più comprensibile e più facilmente manutenibile.
Il nome delle costanti deve avere un significato in base al contesto; ad esempio, è meglio evitare codici del genere SEIZE = 32quando NOMBRE_DE_BITSsarebbe stato più chiaro.
I problemi con questi numeri magici non sono limitati alle costanti numeriche; il termine è utilizzato anche per altri tipi di dati, essendo la dichiarazione di costanti più flessibile e significativa. Quindi dichiarare const string testNomUtilisateur = "Jean"è meglio che usare la parola chiave " Jean" sparsa nel programma; inoltre semplifica la fase di test .
Ad esempio, il seguente pseudo-codice consente di mescolare in modo casuale i valori di un array che rappresenta un mazzo di 52 carte :
for i from 1 to 52 j := i + randomInt(53 - i) - 1 jeu.swapEntries(i, j)dove jeuè un oggetto di tipo array, la funzione randomInt(x)sceglie un numero a caso compreso tra 1 e x incluso e swapEntries(i, j)scambia la posizione dei dati inseriti in i e j nell'array. In questo esempio, 52è un numero magico . Piuttosto, è consigliabile scrivere:
constant int nombreDeCartes := 52 for i from 1 to nombreDeCartes j := i + randomInt(nombreDeCartes + 1 - i) - 1 jeu.swapEntries(i, j)E questo per molte ragioni:
Ci sono ancora alcuni difetti:
In alcuni casi, a seconda delle abitudini di codifica, è accettato l'uso di costanti numeriche senza nome:
Le costanti 1 e 0 sono talvolta utilizzate per rappresentare i valori booleani "True" e "False" nei linguaggi di programmazione che non hanno questo tipo (come le versioni precedenti di C).
In C / C ++ , 0 viene talvolta utilizzato per rappresentare un puntatore o un riferimento nullo . Come nel caso di valori booleani, le librerie C standard contengono macro-definizioni di NULLcui uso è fortemente raccomandato. Altre lingue offrono valori nullo nilspecifici.
È possibile creare o modificare GUID in modo che siano facilmente ricordati sebbene ciò possa influire sulla loro efficienza e unicità. Le regole per la generazione di GUID e UUID sono complesse ma assicurano di avere numeri univoci se vengono seguiti scrupolosamente.
Diversi GUID Java iniziano con " CAFEEFAC ".
Alcuni "numeri magici" sono costituiti da un valore particolare che viene scritto nella RAM durante l'allocazione della memoria per facilitare il debug in caso di crash. Durante il debug, il contenuto della memoria viene solitamente visualizzato in esadecimale . I valori scelti con cura per formare sequenze ripetute di lettere esadecimali, o parole in Hexspeak , sono più facilmente identificabili da un operatore umano.
L'uso di valori dispari è particolarmente utile su processori che non possono indirizzare la memoria a livello di byte , poiché questi andranno in crash se tentano di usarli come puntatori. Allo stesso modo, saranno preferiti i valori che non fanno parte del set di istruzioni .
Poiché è raro che un intero a 32 bit assuma un valore così speciale, la comparsa di uno di questi numeri in un debugger o in un core dump di solito indica un overflow del buffer o una variabile non inizializzata.
Codificato | Descrizione |
---|---|
..FACADE | Utilizzato da molti sistemi operativi in tempo reale |
8BADF00D | Utilizzato da Apple come codice di eccezione nell'iPhone quando un'app impiega troppo tempo per iniziare o terminare |
A5A5A5A5 | Utilizzato su sistemi di bordo perché la sequenza binaria corrispondente (10100101) è facilmente riconoscibile su un oscilloscopio o analizzatore logico |
ABABABAB | Utilizzato dalla funzione HeapAlloc()di Microsoft per contrassegnare la " terra di nessuno " di un byte Guard (in) dopo l'allocazione dell'heap di memoria |
ABADBABE | Utilizzato da Apple come " Boot Zero Block " |
ABADCAFE | Valore di inizializzazione utilizzato per smascherare i puntatori interrotti |
BAADF00D | Utilizzato dalla funzione LocalAlloc(LMEM_FIXED)di Microsoft per contrassegnare l' heap di memoria allocato ma non inizializzato |
BADBADBADBAD | Utilizzato sulle ECU di Burroughs Corporation per individuare la memoria non inizializzata (parola a 48 bit) |
BADC0FFEE0DDF00D | Utilizzato su un sistema RS / 6000 a 64 bit per indicare i registri del processore non inizializzati |
BADCAB1E | Codice di errore restituito dal debugger eVC quando viene interrotta la connessione con il debugger |
BADDCAFE | Su Solaris , contrassegna la memoria del kernel non inizializzata (KMEM_UNINITIALIZED_PATTERN) |
BEEFCACE | Utilizzato nel framework .NET come numero magico per i file di risorse . |
C0DEDBAD | Utilizzato per il debug delle tabelle MMU . |
CAFEBABE | In Mach-O eseguibili ( Fat binary (en) in 68k processori e PowerPC) per identificare i file oggetto e java .class |
CAFEFEED | In Solaris , contrassegnare la memoria allocata dalla funzione kmemfree()per il debug |
CCCCCCCC | Utilizzato dalla libreria di debug C ++ di Microsoft per individuare la memoria dello stack non inizializzata |
CDCDCDCD | Utilizzato da Microsoft C ++ Debugger Library per individuare memoria heap non inizializzata |
CEFAEDFE | Può essere visto nel binario Mach-O per Mac OS X (vedi FEEDFACE) |
DDDDDDDD | Utilizzato da SmartHeap di MicroQuill e C ++ Memory Debugger di Microsoft per contrassegnare la memoria heap liberata |
DEADBABE | Contrassegna l'inizio dei file arena IRIX |
DEADBEEF | Noto per essere utilizzato su sistemi IBM (soprattutto su RS / 6000 ), sul primo Mac OS ( OPENSTEP ) e sul Commodore Amiga . Su Solaris , contrassegnare la memoria del kernel liberata (KMEM_FREE_PATTERN) |
DEADDEAD | Il codice di errore STOP di Windows utilizzato quando l'utente blocca intenzionalmente la macchina |
DEADF00D | Contrassegna tutte le nuove aree di memoria allocate quando non sono state pulite in modo esplicito dopo un danneggiamento |
DEADFA11 | Utilizzato da Apple come codice di eccezione nell'iPhone quando l'utente ha forzato l'arresto di un'app |
EBEBEBEB | Per SmartHeap di MicroQuill |
FADEDEAD | Contrassegna la fine degli script AppleScript |
FDFDFDFD | Utilizzato dal debugger di memoria C ++ per Microsoft per contrassegnare la " terra di nessuno " di un byte Guard (in) prima e dopo l' heap di memoria allocato |
FEE1DEAD | Utilizzato dalla chiamata di sistema reboot()in Linux |
FEEDFACE | Può essere visto sul bit PowerPC Mach-O per Mac OS X . Su Solaris , contrassegna la zona rossa (KMEM_REDZONE_PATTERN) |
FEEEFEEE | Utilizzato dalla funzione HeapFree()di Microsoft per contrassegnare l' heap di memoria rilasciato |
La maggior parte di questi valori ha una dimensione di 32 bit : la dimensione di una parola su processori a 32 bit.
L'uso diffuso di tali valori nelle tecnologie Microsoft non è un caso, poiché questi sono ampiamente riportati nel libro di Steve Maguire (in) Writing Solid Code (in) , presso Microsoft Press (en) . Fornisce diversi criteri per sceglierli:
Poiché sono spesso usati per identificare aree di memoria che dovrebbero essere vuote, a volte tendono ad essere usati nel linguaggio quotidiano nel senso di "perso, abbandonato, svuotato di memoria": ad esempio, "Il tuo programma è DEADBEEF".
Il linguaggio di programmazione ZUG di Pietr Brandehörst inizializza la memoria con i valori 0000, DEADo in FFFFfase di sviluppo, e 0000in produzione, per le variabili non inizializzate restano rilevabili dagli sviluppatori ma minano la parte meno stabile del programma di produzione .