コンピュータプログラミングにおいて、マジックナンバーまたはファイルシグネチャとは、ソースコード内の数値リテラルであり、読者には明確ではない特別な意味を持ちます。また、コンピューティング(プログラミングに限らず)においても、この用語は特定の概念を識別するものの、追加の知識がなければその意味が明確ではない数値を指すために使用されます。例えば、一部のファイル形式は、ファイルに埋め込まれたマジックナンバーによって識別されます。また、ユニバーサルユニーク識別子など、特定の概念と比較的一意に関連付けられた数値も、マジックナンバーに分類される場合があります。
マジックナンバーまたはマジック定数とは、ソースコード内に存在する数値リテラルで、文脈から見て必ずしも明確ではない特別な意味を持ちます。これはアンチパターンとみなされ、1960年代のCOBOL、FORTRAN、PL/1のマニュアルにまで遡る、最も古いプログラミングルールの一つに違反しています。[ 1 ]
たとえば、税込価格を計算する次のコードでは、1.05値が消費税率 5% をわかりにくい方法でエンコードしているため、マジック ナンバーになります。
税引後価格 = 1.05 × 価格
コード内でマジックナンバーを使用すると、開発者がその数字を選んだ意図が不明瞭になり、[ 2 ]微妙なエラーが発生する可能性が高まり、将来的にプログラムの適応や拡張が困難になります。[ 3 ]例えば、すべての数字が正しく入力されているか、または円周率3.14159265358979323846の定数が精度を落としてプログラムの機能に影響を与えずにに切り捨てられるかを判断するのは困難です。すべての重要なマジックナンバーを名前付き定数(説明変数とも呼ばれる)に置き換えることで、プログラムの読みやすさ、理解しやすさ、保守性が向上します。[ 4 ]3.14159
上記の例は、説明的な名前の変数を追加することで改善できます。
税金 = 0.05 税引後価格 = (1.0 + 税金) * 価格
適切な名前を付けると、元の作者ではないメンテナーや、時間が経てば元の作者自身でさえも理解しやすくなるコードを作成できます。[ 5 ]情報量の少ない名前の定数の例としては がありますがint SIXTEEN = 16、 の方int NUMBER_OF_BITS = 16が便利かもしれません。
数値以外のデータもマジックナンバーと同様の魔法の特性を持つ可能性があり、そのためマジックナンバーと同様の問題が発生することがあります。[ 1 ]そのため、リテラルを直接使用するよりも宣言しconst string testUserName = "John"て使用する方がよい場合があります。 testUserName"John"
たとえば、標準的なトランプのパックを表す配列内の値をランダムにシャッフルする必要がある場合、次の疑似コードは、 Fisher–Yates シャッフルアルゴリズムを使用してその処理を実行します。
iは1から52まで j := i + ランダム整数(53 - i) - 1 a.swapEntries(i, j)
が配列オブジェクトである場合a、関数は1からxrandomInt(x)まで(両端を含む)のランダムな整数を選択し、配列のi番目とj番目の要素を入れ替えます。前の例では、とがマジックナンバーであり、互いに明確な関連性はありません。より適切なプログラミングスタイルとして、次のように記述します。 swapEntries(i, j)5253
int deckSize:= 52、 iは1からdeckSizeまで j := i + ランダム整数(デッキサイズ + 1 - i) - 1 a.swapEntries(i, j)
これはいくつかの理由から好ましいです:
deckSize、単純な 1 行の変更になります。dekSize」ではなく「deckSize」と入力すると、宣言されていないというコンパイラの警告が表示されますdekSize。deckSizeその手順のパラメータに変換するだけで十分ですが、最初の例ではいくつかの変更が必要になります。関数shuffle ( int deckSize) はi を1からdeckSizeまで変化させます。 j := i + ランダム整数(デッキサイズ + 1 - i) - 1 a.swapEntries(i, j)
デメリットは次のとおりです。
deckSize + 1。実行時に式を処理する方が、値「53」よりも遅くなる可能性があります。とはいえ、最近のコンパイラのほとんどは、定数畳み込みやループ最適化などの手法を用いてコンパイル時に加算を解決するため、コード内でマジックナンバーを使用する場合と比べて、速度の低下は通常、全くないか、ごくわずかです。特に、デバッグにかかるコストや、説明のつかないコードを理解するのにかかる時間は、わずかな計算コストと比べるべきです。数値リテラルに特別な意味がない場合、その使用は魔法とは分類されませんが、何が特別な意味を持つかは主観的なものです。魔法と見なされないことが多いリテラルの例としては、以下のものがあります。
for(inti=0;i<max;i+=1)isEven = (x % 2 == 0)です。%circumference = 2 * Math.PI * radius、[ 1 ]のような式や、二次方程式の判別式を計算する場合などd = b^2 − 4*a*c(f(x) ** 2 + f(y) ** 2) ** 0.5次のような式における指数NULLnullptrフォーマット インジケーターは、初期のバージョン 7 Unixソース コードで初めて使用されました。
Unixはメモリ保護を持たない初期のDEC PDP-11 /20に移植された。そのため、初期のUnixでは再配置可能メモリ参照モデルが使用されていた。[ 6 ]第6版より前のUnixバージョンでは、実行可能ファイルをメモリに読み込み、プログラムの最初の下位メモリアドレス(相対アドレス0)にジャンプしていた。ページングバージョンのUnixの開発に伴い、実行可能イメージのコンポーネントを記述するヘッダーが作成された。また、ヘッダーの最初のワードとして分岐命令が挿入され、ヘッダーをスキップしてプログラムを開始できるようになった。このようにして、プログラムは従来の再配置可能メモリ参照(通常)モードまたはページングモードで実行できた。より多くの実行可能形式が開発されるにつれて、分岐オフセットを増分することで新しい定数が追加された。[ 7 ]
Unix プログラム ローダーの第6 版のソース コードでは、exec() 関数がファイル システムから実行可能 (バイナリ) イメージを読み取ります。ファイルの最初の 8バイトは、プログラム (テキスト) と初期化された (グローバル) データ領域のサイズを含むヘッダーです。また、ヘッダーの最初の 16 ビット ワードは 2 つの定数と比較され、実行可能イメージに再配置可能なメモリ参照(通常)が含まれているか、新しく実装されたページ化された読み取り専用の実行可能イメージが含まれているか、命令とデータが分離されたページ化されたイメージが含まれているかが判断されます。[ 8 ]ヘッダー定数の 2 つの役割については触れられていませんが、定数の上位バイトは実際にはPDP-11 分岐命令の操作コード(8進数で 000407、16 進数で0107 ) でした。プログラム カウンタに 7 を追加すると、この定数が実行されると、Unix exec() サービスが実行可能イメージの 8 バイト ヘッダーを介して分岐し、プログラムが起動することが示されました。
Unixの第6版および第7版ではページングコードが採用されていたため、ヘッダー定数の二重の役割は隠蔽されていました。つまり、exec() サービスは実行ファイルのヘッダー(メタ)データをカーネル空間バッファに読み込みますが、実行イメージはユーザー空間に読み込むため、定数の分岐機能は使用されませんでした。マジックナンバーの生成はUnixのリンカーとローダーに実装されており、マジックナンバーによる分岐は、第6版および第7版に付属していたスタンドアロン診断プログラム群では依然として使用されていたと考えられます。したがって、ヘッダー定数は確かに錯覚を引き起こし、マジックナンバーの基準を満たしていました。
バージョン7のUnixでは、ヘッダー定数は直接テストされず、 ux_mag [ 9 ]という変数に割り当てられ、その後マジックナンバーと呼ばれるようになりました。おそらくその独自性から、マジックナンバーという用語は実行可能フォーマットの種類を意味するようになり、その後ファイルシステムの種類を意味するようになり、さらにあらゆる種類のファイルを意味するようになりました。
マジックナンバーは、多くのオペレーティングシステムのプログラムでよく使用されます。マジックナンバーは、厳密に型指定されたデータを実装し、プログラム実行時にデータ型を読み取る制御プログラムへの帯域内シグナリングの一種です。多くのファイルには、含まれるデータを識別するこのような定数が含まれています。ファイル内のこのような定数を検出することは、多くのファイル形式を区別するためのシンプルで効果的な方法であり、実行時の詳細情報も得ることができます。
CA FE BA BE。Pack200で圧縮すると、バイトは に変更されますCA FE D0 0D。47 49 46 38 39 61)または「GIF87a」(47 49 46 38 37 61)です。FF D8で終わりますFF D9。JPEG/ JFIFファイルには、ヌルで終了する文字列「JFIF」( 4A 46 49 46 00) が含まれます。JPEG/ Exifファイルには、ヌルで終了する文字列「Exif」( 45 78 69 66 00) と、それに続くファイルに関するメタデータが含まれます。89 50 4E 47 0D 0A 1A 0A署名で始まり、一般的なファイル転送の問題を検出することができます: "\211PNG\r\n\032\n" ( )。この署名には様々な改行文字が含まれており、 FTPでバイナリモードではなくASCII転送モードでファイルを転送するなど、不必要な自動改行変換を検出することができます。[ 10 ]4D 54 68 6423 21へのパスが続くことがあります。7F実行ファイルは、"ELF" ( ) が続くバイトで始まります7F 45 4C 46。25 21) で始まります。25 50 44 46) で始まります。4D 5A5A 4D19 54 01 19またはとして識別されます01 19 54。どちらも作成者であるMarshall Kirk McKusickの誕生日を表しています。55 AA4A 6F 79 2149 49 2A 004D 4D 00 2AFE FFFF FEEF BB BF42 43) で始まります。D0 CF 11 E0、視覚的には「DOCFILE0」という単語を連想させます。50 4B 03 04のイニシャルです。37 7A BC AF 27 1C) で始まります。Unixユーティリティプログラムはfile、ファイルからマジックナンバーを読み取って解釈することができ、その情報を解析するために使用されるファイルはmagicと呼ばれます。WindowsユーティリティTrIDも同様の目的を持っています。
2A52 46 42FF 53 4D 42、または\xFFSMBSMB 要求の先頭で始まります。05リクエストの先頭に (Microsoft DCE/RPC バージョン 5 を表す)で始まり、その直後にマイナーバージョンを表す00または が続きます01。UDP ベースの MSRPC リクエストでは、最初のバイトは常に です04。4D 45 4F 57)で始まります。デバッグ拡張機能(DCOMチャネルフックに使用される)は、バイトシーケンス「MARB」(4D 41 52 42)で始まります。19、その直後にバイト位置 1 に「BitTorrent プロトコル」というフレーズが続きます。E3eDonkey クライアント、C5eMule、D4圧縮された eMule を表します。D9 B4 BE F9、メインネットワークを示し、 はDA B5 BF FAテストネットを示します。80SSLv3のclient helloメッセージに対するサーバー応答は で始まります16(ただし、これは異なる場合があります)。63 82 53 63パケットは、パケットのオプションセクションの先頭に「マジッククッキー」値を使用します。この値は、すべてのDHCPパケットタイプに含まれています。PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n。これは、HTTP 2.0 ではなく、以前のバージョンの HTTP をサポートするサーバーや中継サーバーによるフレーム処理を回避するように設計されています。258EAFA5-E914-47DA-95CA-C5AB0DC85B11。マジック ナンバーは、 DOS、Windows、NetWareなど、多くのオペレーティング システムのAPI 関数およびインターフェイスでよく使用されます。
00 00、12 34システムが再起動時にメモリをカウントアップするかどうかを決定し、コールドブートまたはウォームブートを実行します。これらの値は、EMM386メモリマネージャがブート要求を傍受する際にも使用されます。[ 12 ]55 AA BIOSは、ディスクがブート可能かどうかを判断するためにもマジック値を使用します。 [ 13 ]BA BEとEB ABAPI関数を使用します。[ 12 ]0E DCグローバル一意識別子(GUID)を覚えやすいように作成または変更することは可能ですが、ほぼ一意の識別子としての強度が損なわれるため、これは強く推奨されません。 [ 15 ] [ 16 ] GUIDとUUIDを生成するための仕様は非常に複雑であり、適切に実装されていれば、それらは事実上一意になります。[ 17 ]
Microsoft Office製品の Microsoft Windows 製品 ID 番号は、("OFFICE")で終わる場合があります0000-0000-0000000FF1CE。たとえば90160000-008C-0000-0000-0000000FF1CE、「Office 16 Click-to-Run Extensibility Component」の製品 ID は です。
Javaでは、で始まるいくつかのGUIDが使用されますCAFEEFAC。[ 18 ]
GPTパーティションスキームのGUIDパーティションテーブルでは、 BIOSブートパーティションはGUID定義に従わない特別なGUID 21686148-6449-6E6F-744E-656564454649[ 19 ]を使用します。代わりに、文字列のASCIIHah!IdontNeedEFIコードを部分的にリトルエンディアン順序で使用して形成されます。[ 20 ]
マジックデバッグ値とは、メモリの割り当て時または解放時に書き込まれる特定の値です。これにより、後でメモリが破損しているかどうかを確認したり、初期化されていないメモリから取得された値が使用されている場合、そのことが明確になります。メモリは通常16進数で表現されるため、記憶に残りやすい繰り返し値や16進数で表現される値が一般的です。バイトアドレス指定に対応していないプロセッサがポインタ(偶数アドレスに指定する必要がある)として使用しようとした場合にエラーが発生するため、数値的に奇数値が推奨されます。値は、プログラムコード、静的データ、ヒープデータ、スタックなどのアドレスから離れた場所を選択する必要があります。同様に、特定のアーキテクチャの命令セットにおいて有効なコードではない値を選択することもできます。
32 ビット整数がこの特定の値を取る可能性は非常に低いですが、デバッガーやメモリ ダンプにこのような数値が表示される場合は、バッファー オーバーフローや初期化されていない変数などのエラーが発生している可能性が高くなります。
有名で一般的な例としては次のようなものがあります。
| コード | 説明 |
|---|---|
00008123 | MS Visual C++で使用されます。削除されたポインタはこの値に設定されるため、その後使用されると例外がスローされます。これはゼロアドレスのより分かりやすい別名です。セキュリティ開発ライフサイクル(/sdl)オプションで有効化されます。[ 21 ] |
..FACADE | 「Facade」は、多くのRTOSで使用されます。 |
1BADB002 | 「1 bad boot」、マルチブートヘッダーのマジックナンバー。[ 22 ] |
8BADF00D | 「まずいものを食べた」は、ウォッチドッグタイムアウトが発生したためにApple iOSアプリケーションが終了したことを示します。[ 23 ] |
A5A5A5A5 | 交互のビットパターン (1010 0101) により、オシロスコープやロジック アナライザで簡単に認識できるパターンが作成されるため、組み込み開発で使用されます。 |
A5 | この値は NULL ポインターまたは ASCII NUL 文字ではないため、/etc/malloc.conf が "-J" にシンボリックリンクされている場合に、 FreeBSDの PHK malloc(3)でデバッグのために使用されます。 |
ABABABAB | マイクロソフトのデバッグHeapAlloc()で使用され、割り当てられたヒープメモリの後に「無人地帯」ガードバイトをマークします。[ 24 ] |
ABADBABE | 「A bad babe」 、 Appleが「Boot Zero Block」マジックナンバーとして 使用。 |
ABBABABE | 「ABBAベイブ」、ドライバーによって使用される: Parallel Linesメモリ ヒープ。 |
ABADCAFE | 「A bad cafe」、割り当てられていないすべてのメモリを初期化するために使用されます (Mungwall、AmigaOS )。 |
B16B00B5 | 「Big Boobs」は、以前はMicrosoftのHyper-VハイパーバイザーでLinuxゲストの「ゲストID」の上位半分として使用するために必要とされていました。[ 25 ] |
BAADF00D | 「Bad food」は、 MicrosoftのデバッグHeapAlloc()で使用され、初期化されていない割り当てられたヒープメモリをマークします。 [ 24 ] |
BAAAAAAD | 「Baaaaaad」は、Apple iOSのログがクラッシュレポートではなく、システム全体のスタックショットであることを示します。[ 23 ] |
BAD22222 | 「頻繁に再開しすぎる」は、Apple iOS VoIPアプリケーションが頻繁に再開したために終了したことを示します。[ 23 ] |
BADBADBADBAD | 「悪い、悪い、悪い、悪い」、バローズの大規模システムの「初期化されていない」メモリ(48 ビット ワード)。 |
BADC0FFEE0DDF00D | 「Bad coffee odd food」 、 IBM RS/6000 64 ビット システム で、初期化されていない CPU レジスタを示すために使用されます。 |
BADDCAFE | 「Bad cafe」は、Sun MicrosystemsのSolarisでは、初期化されていないカーネル メモリ (KMEM_UNINITIALIZED_PATTERN) をマークします。 |
BBADBEEF | 「Bad beef」はWebKitで使用され、特に回復不可能なエラーを指します。[ 26 ] |
BEBEBEBE | AddressSanitizerによって、割り当てられたが初期化されていないメモリを埋めるために使用されます。[ 27 ] |
BEEFCACE | 「ビーフ ケーキ」は、 Microsoft .NETによってリソース ファイル内のマジック ナンバーとして使用されます。 |
C00010FF | 「クールオフ」は、Apple iOSアプリが熱イベントに反応してオペレーティングシステムによって強制終了されたことを示します。[ 23 ] |
CAFEBABE | 「Cafe babe」、Javaによってクラス ファイルに使用されます。 マルチアーキテクチャMach-Oバイナリで使用されます。 |
CAFED00D | 「Cafe dude」、Javaのpack200圧縮に使用されます。 |
CAFEFEED | 「カフェ フィード」は、 Sun MicrosystemsのSolarisデバッグ カーネルによって使用され、kmemfree() メモリをマークします。 |
CCCCCCCC | マイクロソフトのC++デバッグランタイムライブラリや多くのDOS環境で初期化されていないスタックメモリをマークするために使用されます。x86プロセッサのINT 3デバッグブレークポイント割り込みCCのオペコードです。 [ 28 ] |
CDCDCDCD | MicrosoftのC/C++デバッグmalloc()関数で、初期化されていないヒープメモリをマークするために使用されます。通常はから返されますHeapAlloc。[ 24 ] |
0D15EA5E | 「Zero Disease」は、 GameCubeおよびWiiコンソールで通常の起動を示すフラグとして使用されます。 |
DDDDDDDD | MicroQuillのSmartHeapとMicrosoftのC/C++デバッグのfree()関数で、解放されたヒープメモリをマークするために使用されます。[ 24 ] |
DEAD10CC | 「デッドロック」とは、Apple iOSアプリケーションがバックグラウンドで実行中にシステムリソースを保持していたために終了したことを示します。[ 23 ] |
DEADBABE | 「Dead babe」は、 Silicon GraphicsのIRIXアリーナ ファイルの先頭で使用されます。 |
DEADBEEF | 「デッドビーフ」は、 RS/6000などのIBMシステムでよく使用され、クラシックなMac OSオペレーティングシステム、OPENSTEP Enterprise、Commodore Amigaでも使用されています。Sun MicrosystemsのSolarisでは、解放されたカーネルメモリ(KMEM_FREE_PATTERN)をマークします。 |
DEADCAFE | 「Dead cafe」は、 Microsoft .NETによってDLL内のエラー番号として使用されます。 |
DEADC0DE | 「デッド コード」は、 OpenWRTファームウェアのマーカーとして使用され、静的ファームウェアの最後に作成される jffs2 ファイル システムの開始を示します。 |
DEADFA11 | 「Dead fail」は、Apple iOSアプリケーションがユーザーによって強制終了されたことを示します。[ 23 ] |
DEADF00D | 「デッドフード」は、コモドールアミガのMungwallが割り当て済みだが初期化されていないメモリをマークするために使用しました。[ 29 ] |
DEFEC8ED | 「Defecated」、OpenSolarisコア ダンプに使用されます。 |
DEADDEAD | 「Dead Dead」は、ユーザーがカーネルデバッガーまたはMicrosoft Windowsのキーボードから意図的にクラッシュダンプを開始したことを示します。[ 30 ] |
D00D2BAD | 「おい、残念だ」、 Safariで使用されているアプリがmacOS Big Surでクラッシュする。[ 31 ] |
D00DF33D | 「Dudeフィード」は、デバイスツリーによってヘッダーの開始を示すために使用されます。[ 32 ] |
EBEBEBEB | MicroQuill の SmartHeap から。 |
FADEDEAD | 「Fade dead」は、すべてのAppleScriptスクリプトを識別するために最後に表示されます。 |
FDFDFDFD | マイクロソフトのC/C++デバッグmalloc()関数で、割り当てられたヒープメモリの前後に「無人地帯」ガードバイトをマークするために使用され、 [ 24 ]マイクロソフトによって実装されたいくつかのデバッグセキュアCランタイム関数(例:strncat_s)でも使用されます。[ 33 ] |
FEE1DEAD | 「Feel dead」、Linux のreboot() システムコールによって使用されます。 |
FEEDFACE | 「フィード面」は、Apple社のMac OSXプラットフォームのMach-Oバイナリで見られます。Sun Microsystems社のSolarisでは、レッドゾーン(KMEM_REDZONE_PATTERN)を示します。 VLCプレーヤーと一部のIPカメラはRTP / RTCPプロトコルでこのマジックナンバーを使用します。VLCプレーヤーはシステムのエンディアン順序に従って4バイトを送信します。一部のIPカメラは、プレーヤーからのこのマジックナンバーの送信を期待しており、受信されない場合、ストリームを開始しません。 |
FEEEFEEE | 「Fee fee」は、Microsoftのデバッグ用HeapFree()で、解放されたヒープメモリをマークするために使用されます。一部の内部ブックキーピング値にも、上位ワードがFEEEに設定されている場合があります。[ 24 ] |
これらのほとんどは 32ビット長で、これはほとんどの 32 ビット アーキテクチャ コンピュータの ワード サイズです。
これらの価値観がマイクロソフトのテクノロジーに広く浸透しているのは偶然ではありません。Microsoft PressのSteve Maguire氏の著書『Writing Solid Code』で詳しく解説されています。彼はこれらの価値観について、以下のような様々な基準を挙げています。
これらは本質的に空であるメモリ領域をマークするためによく使用されるため、これらの用語の一部は「メモリから消えた、中止された、フラッシュされた」という意味のフレーズで使用されるようになりました。たとえば、「Your program is DEADBEEF」などです。