C のグローバル初期化順序 : 依存関係の無視
C では、翻訳単位内のグローバル変数の初期化順序が明確に定義されています。ただし、グローバル間の依存関係は無視され、予期しない動作につながる可能性があります。
次のコードを考えてみましょう:
<code class="cpp">struct Foo; extern Foo globalFoo; struct Foo { Foo() { printf("Foo::Foo()\n"); } void add() { printf("Foo::add()\n"); } static int addToGlobal() { printf("Foo::addToGlobal() START\n"); globalFoo.add(); printf("Foo::addToGlobal() END\n"); return 0; } }; Foo globalFoo; int dummy = Foo::addToGlobal(); int main() { printf("main()\n"); return 0; }</code>
GCC 4.4.3 でコンパイルすると、予期される出力は次のようになります。
Foo::Foo() Foo::addToGlobal() START Foo::add() Foo::addToGlobal() END main()
これは、静的メソッド Foo::addToGlobal() を呼び出す前にグローバル変数 globalFoo が初期化されるためです。ただし、globalFoo とダミー宣言の順序を入れ替えると、出力は次のようになります。
Foo::addToGlobal() START Foo::add() Foo::addToGlobal() END Foo::Foo() main()
Foo のインスタンス メソッドが、構築されていないインスタンスで呼び出されているようです。これは、グローバル初期化の順序が依存関係を無視するためです。
ダミーを初期化する前に Foo のコンストラクターが確実に呼び出されるようにするには、同じ翻訳単位でダミーの前に globalFoo が定義されていることを確認する必要があります。あるいは、動的初期化の前に null に初期化されるグローバル インスタンスへの静的ポインターを使用することもできます。その後、addToGlobal メソッドはポインターが null かどうかを確認し、必要に応じてグローバル Foo を作成します。
以上がC でグローバル変数宣言を交換すると予期しない動作が起こるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。