4

私の知る限り、(Linux で C++ で作成された) プログラムは__cxa_finalize、メイン関数を終了するときに呼び出します。共有ライブラリを作成し、このライブラリをメイン関数で使用します。メイン プログラムがこのライブラリをロード/アンロードするときに、いくつかのアクションを実行したいと考えています。共有ライブラリを作成するときに、その目的で関数を使用できることがわかりました__attribute__(この関数は、共有ライブラリコードに実装されると思います)

次のように追加しました:

void __attribute__ ((constructor)) my_load(void);

void __attribute__ ((destructor)) my_unload(void);

次のリンクのように関数 my_load と my_unload を実装しました: http://tdistler.com/2007/10/05/implementing-dllmain-in-a-linux-shared-library

問題は、メイン関数を終了するときにこれらの関数が正確にどの順序で処理されるかです。my_unload()関数または__cxa_finalize

4

2 に答える 2

2

コンストラクタ/デストラクタ属性の gcc ドキュメントには、次のように記載されています

オプションの整数の優先順位を指定して、コンストラクター関数とデストラクター関数が実行される順序を制御できます。優先度の数値が小さいコンストラクターは、優先度の数値が大きいコンストラクターの前に実行されます。逆の関係がデストラクタに当てはまります。そのため、リソースを割り当てるコンストラクタと同じリソースの割り当てを解除するデストラクタがある場合、通常、両方の関数の優先度は同じです。コンストラクター関数とデストラクター関数の優先度は、名前空間スコープの C++ オブジェクトに指定されている優先度と同じです。

ただし、gcc-4.7.0 を使用した私のテストでは、宣言/定義の順序に関係なく、両方が同じ翻訳単位にある場合、コンストラクター関数は C++ グローバル オブジェクト コンストラクターの前に実行され、デストラクタ関数は C++ グローバル オブジェクト デストラクタの後に実行されます。

更新: Ian Lance Taylor は、constructor 属性と C++ グローバル コンストラクターを持つ関数の実行順序が指定されていないと報告しました。http://gcc.gnu.org/ml/gcc-help/2012-05/msg00118.htmlを参照してください。

C++ では、 Schwarz Counterイディオムを使用して、いくつかのオブジェクトが他のグローバル オブジェクトの前に初期化され、その後複数の翻訳単位で破棄されるようにすることができます。

于 2012-05-17T14:27:34.637 に答える
0

メイン プログラムがこのライブラリをロード/アンロードするときに、いくつかのアクションを実行したいと考えています。

そのために静的クラス インスタンスを使用することを検討してください。よりクリーンで移植性が高くなります。

基本的に、コンストラクターで初期化作業 (およびデストラクタでファイナライズ) を行うクラスを作成し、そのクラスの静的インスタンスを宣言します。その後、動的リンカーがすべてを行います。

LLVM には、この手法を使用してプラグインのレジストリを自動的に管理する優れたクラス テンプレートがあります。それから学習することをお勧めします。

于 2012-05-18T17:13:45.390 に答える