システム起動時の初期化
標準Cでは、固定メモリアドレスに割り当てられるすべての静的変数は、アプリケーション起動時にランタイムシステムにより既知の値に初期化される必要があります。この値は、変数に明示的に割り当てられた値か、値が指定されていない場合はゼロにクリアされます。コンパイラには、この規則の例外があります。たとえば、__no_init宣言される変数です。これはまったく初期化されません。
コンパイラは、変数初期化の各型に対して、特定の型のセクションを生成します。
宣言データのカテゴリ | ソース | セクション型 | セクション名 | セクションの内容 |
|---|---|---|---|---|
ゼロで初期化されるデータ | int i; | リード/ライトデータ、ゼロ初期化 |
| なし |
ゼロで初期化されるデータ | int i = 0; | リード/ライトデータ、ゼロ初期化 |
| なし |
初期化されるデータ(ゼロ以外) | int i = 6; | リード/ライトデータ |
| イニシャライザ |
非初期化データ | __no_init int i; | リード/ライトデータ、ゼロ初期化 |
| なし |
定数 | const int i = 6; | リードオンリーデータ |
| 定数 |
コード | __ramfunc void myfunc() {} | リード/ライトコード |
| コード |
注記
静的変数をクラスタ化すると、ゼロで初期化される変数と初期化されるデータが一緒に.dataにグループ化される可能性があります。定数テーブルから定数のアドレスをロードしなくていいように、コンパイラは定数を.textセクションに配置するよう決定できます。
サポートされているすべてのセクションについては、「セクションリファレンス」を参照してください。
初期化プロセス
データの初期化は、ILINKおよびシステム起動コードで扱われます。
変数の初期化を設定するには、以下のことを考慮する必要があります。
ゼロ初期化されたセクション、または初期化されていないセクション(
__no_init)はILINKが自動的に処理します。初期化されるセクションは、ゼロ初期化されるセクションを除き、
initializeディレクティブにリストされていなければなりません。通常、リンク時に、初期化されるセクションは、2つのセクションに分割されます。ここで、元の初期化されるセクションはその名前を保持します。その内容は新しいイニシャライザセクションに配置され、サフィックス
_initが付いた元の名前を取得します。配置ディレクティブにより、イニシャライザはROMに、初期化されるセクションはRAMに配置されます。この最も一般的な例は、.dataセクションです。このセクションは、リンカにより.dataおよび.data_initに分割されます。定数を含むセクションは初期化されません。このようなセクションは、フラッシュ/ROMにのみ配置されます。
リンカ設定ファイルでは、次のように定義されています。
/* Handle initialization */
initialize by copy { readwrite }; /* Initialize RW sections */
/* Place startup code at a fixed address */
place at start of ROM { readonly section .cstartup };
/* Place code and data */
place in ROM { readonly }; /* Place constants and initializers in
ROM: .rodata and .data_init */
place in RAM { readwrite, /* Place .data, .bss, and .noinit */
block STACK }; /* and STACK */注記
圧縮されたイニシャライザが使用される場合( initialize directiveを参照)、内容のセクション(つまり、_initサフィックスの付いたセクション)はマップファイルで個別のセクションとしてはリストされません。その代わりに、これらは「イニシャライザバイト」の集合に組み込まれます。コンテンツセクションを通常のようにリンカ設定ファイルに配置できますが、こうすることでイニシャライザバイトの集合の配置(およびそ数)に影響が出ます。
初期化の設定方法の詳細および例については、リンクについてを参照してください。
C++動的初期化
コンパイラは、C++の動的初期化を実行するためのサブルーチンポインタを、ELFセクションタイプSHT_PREINIT_ARRAYおよびSHT_INIT_ARRAYのセクションに配置します。デフォルトでは、リンカはこれらをリンカが作成したブロックに配置し、セクションタイプSHT_PREINIT_ARRAYのセクションがすべてタイプSHT_INIT_ARRAYの前に配置されるようにします。このようなセクションが含まれる場合、ルーチンを呼び出すコードも含まれることになります。
リンカが作成したブロックは、リンカ設定にpreinit_arrayおよびinit_arrayセクションタイプのセクションセレクタのパターンが含まれない場合にのみ生成されます。リンカにより作成されたブロックの効果は、リンカ設定ファイルに以下が含まれる場合と同じようになります。
define block SHT$$PREINIT_ARRAY { preinit_array };
define block SHT$$INIT_ARRAY { init_array };
define block CPP_INIT with fixed order { block SHT$$PREINIT_ARRAY,
block SHT$$INIT_ARRAY };これをリンカ設定ファイルに入れる場合、セクション配置ディレクティブのいずれかでCPP_INITブロックも記述する必要があります。リンカにより作成されたブロックをどこに配置するか選択する場合は、".init_array"という名前のセクションセレクタを使用できます。
section-selectorsも参照してください。