ここでの答えは、 __attribute__((constructor)) が静的初期化後に呼び出されず、宣言順に呼び出されることを示しています。
では、すべてのデータが初期化されたときに呼び出されることが保証されていない場合、その目的は何ですか? Foo コンストラクターに ((constructor)) コードを含めることもできます。
私が探しているのは、共有ライブラリで、すべての静的データが初期化され、静的コンストラクターが呼び出された後に実行されるコードを持つ方法です。DllMain; の代わりとして __attribute__((constructor)) を推奨している人を見ました。一部の静的データがまだ初期化されていない可能性があるため、これは間違っていることがわかります。
もちろん、単一のファイル (コンパイル単位) では、静的を配置できます。しかし、典型的なプログラムにはたくさんのファイルがあります。共有ライブラリ内の他のすべての statics が初期化された後に、1 つのファイル内の ((constructor)) が確実に呼び出されることを保証する方法はありますか?
静的初期化 (コンストラクター、オブジェクトなど) を含むファイルを gcc コマンド ラインの末尾に配置すると、次のようになります。
g++ -shared -fPIC source1.o source2.o MyLastInitChance.o
このファイルの静的コンストラクターは最後に呼び出されることが保証されていますか? 実験したところ、ソースファイルの順序を変更すると、printfs の順序が変更されました。しかし、それはどこかで指定されており、コンパイルシステム/コンピューター間で同じであることが保証されていますか?
たとえば、引用:
リンク時に、gcc ドライバーはすべての再配置可能ファイルの直前に crtbegin.o を配置し、すべての再配置可能ファイルの直後に crtend.o を配置します。©
私が理解していることから、上記の引用は、リンカーに渡される .o ファイルの順序が静的初期化の順序を定義することを意味します。私は正しいですか?
もう 1 つの興味深い解決策は、静的初期化を調整する GCC プラグインを作成することです (たとえば、コードを .ctors セクションに追加するなど)。しかし、これはおそらく誰かが拡張できるアイデアにすぎません。
もう 1 つの可能な解決策をここに示します。つまり、外部のビルド後ツールを使用して、実行可能ファイル (ライブラリ) 内の .ctors エントリを並べ替えることができます。しかし、私は ELF 形式の専門家ではありません。これが可能であり、この方法で .so ファイルを微調整するのに十分簡単かどうか疑問に思います。
私が興味を持っているのは、特定の問題を解決すること、または解決できないことを証明することです (少なくとも、上記の解決策が機能しない理由)。