init_seg

C++ 仕様

スタートアップ コードの実行順序に影響を与えるコード例やキーワードを指定します。

#pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )

解説

用語の意味は 分割し それらについては このトピックで交換できます。

グローバルな静的オブジェクトの初期化はコードの実行を含めることができるためオブジェクトがいつ構築する必要があるかを定義するキーワードを指定する必要があります。初期化を必要とするダイナミック リンク ライブラリ (DLLs) またはライブラリに init_seg のプラグマを使用すると特に重要です。

init_seg のプラグマに次のオプションがあります。:

  • コンパイラ
    Microsoft C ランタイム ライブラリを初期化するために予約されています。このグループ オブジェクトが最初に作成されます。

  • ライブラリ
    サードパーティ ベンダーのクラス ライブラリを初期化するために使用できます。このグループ オブジェクトが コンパイラ としての他の前にマークされたブロックの後に生成されます。

  • ユーザー
    ユーザーに対して使用できます。このグループ オブジェクトが最後に構築されます。

  • セクション名
    初期化のセクションでは明示的な指定します。ユーザー指定の セクション名 のオブジェクトは暗黙的に組み立てられません ; ただし住所 セクション名 で指定したセクションに格納されます。

    によってセクション名はプラグマの後にそのモジュールで宣言されたグローバル オブジェクトを構築するヘルパー関数へのポインターが格納されます。

    使用するな名前の一覧については" " を作成し/SECTION を参照してください。

  • 機能名前
    atexit の代わりに呼び出す関数をプログラムの終了時に指定します。このヘルパー関数はグローバル オブジェクトのデストラクターへのポインターで atexit を呼び出します。フォームのプラグマで関数の識別子を指定すると

    int __cdecl myexit (void (__cdecl *pf)(void))
    

    次に関数は C ランタイム ライブラリの atexit の代わりに呼び出されます。これはオブジェクトを破棄する準備が整った時点で呼び出す必要があるデストラクターのリストを作成することができます。

初期化を延期する必要がある場合 (たとえばDLL のセクション名を明示的に指定する場合) を選択できます。その後各静的オブジェクトのコンストラクターを呼び出す必要があります。

見積もりは atexit の置換の識別子にありません。

オブジェクトはXXX_seg の他のプラグマで定義したセクションに格納されます。

モジュールで宣言されているオブジェクトは C のランタイムで自動的に初期化します。に自分する必要があります。

既定ではinit_seg のセクションは読み取り専用です。.CRT セクション名がである場合コンパイラは読み取るために読み込まれるようにマークされても自動的に属性を変更します。

翻訳単位で init_seg を複数回指定できません。

オブジェクトにはユーザー定義のコンストラクターがない場合でも明示的にコードで定義されていないコンストラクターは1 を生成することがあります。たとえば v-table のポインターをバインドします)。このコードはコンパイラによって生成されたコンストラクターを呼び出す必要があります。

使用例

// pragma_directive_init_seg.cpp
#include <stdio.h>
#pragma warning(disable : 4075)

typedef void (__cdecl *PF)(void);
int cxpf = 0;   // number of destructors we need to call
PF pfx[200];    // pointers to destructors.

int myexit (PF pf) {
   pfx[cxpf++] = pf;
   return 0;
}

struct A {
   A() { puts("A()"); }
   ~A() { puts("~A()"); }
};

// ctor & dtor called by CRT startup code 
// because this is before the pragma init_seg
A aaaa; 

// The order here is important.
// Section names must be 8 characters or less.
// The sections with the same name before the $
// are merged into one section. The order that
// they are merged is determined by sorting
// the characters after the $.
// InitSegStart and InitSegEnd are used to set
// boundaries so we can find the real functions
// that we need to call for initialization.

#pragma section(".mine$a", read)
__declspec(allocate(".mine$a")) const PF InitSegStart = (PF)1;

#pragma section(".mine$z",read)
__declspec(allocate(".mine$z")) const PF InitSegEnd = (PF)1;

// The comparison for 0 is important.
// For now, each section is 256 bytes. When they
// are merged, they are padded with zeros. You
// can't depend on the section being 256 bytes, but
// you can depend on it being padded with zeros.

void InitializeObjects () {
   const PF *x = &InitSegStart;
   for (++x ; x < &InitSegEnd ; ++x)
      if (*x) (*x)();
}

void DestroyObjects () {
   while (cxpf>0) {
      --cxpf;
      (pfx[cxpf])();
   }
}

// by default, goes into a read only section
#pragma init_seg(".mine$m", myexit)

A bbbb; 
A cccc;

int main () {
   InitializeObjects();
   DestroyObjects();
}
  

参照

関連項目

プラグマのディレクティブと __Pragma のキーワード