init_seg プラグマinit_seg pragma

C++のみC++ Specific

スタートアップ コードが実行される順序に影響を与えるキーワードまたコード セクションを指定します。Specifies a keyword or code section that affects the order in which startup code is executed.

構文Syntax

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

RemarksRemarks

この記事では、セグメントセクションという用語は同じ意味を持ちます。The terms segment and section have the same meaning in this article.

グローバルな静的オブジェクトの初期化にはコードが必要になることがあるため、オブジェクトを構築するタイミングを指定する必要があります。Because code is sometimes required to initialize global static objects, you must specify when to construct the objects. 特に、ダイナミックリンクライブラリ (Dll) または初期化が必要なライブラリでは、 init_segプラグマを使用することが重要です。In particular, it's important to use the init_seg pragma in dynamic-link libraries (DLLs), or in libraries that require initialization.

Init_segプラグマのオプションは次のとおりです。The options to the init_seg pragma are:

コンパイラーcompiler
Microsoft C ランタイム ライブラリの初期化のために予約されています。Reserved for Microsoft C run-time library initialization. このグループ内のオブジェクトが最初に構築されます。Objects in this group are constructed first.

変数lib
サード パーティの開発元のクラス ライブラリの初期化に使用できます。Available for third-party class-library vendors' initializations. このグループのオブジェクトは、コンパイラとしてマークされているオブジェクトの後、他のオブジェクトの前に構築されます。Objects in this group are constructed after the ones marked as compiler, but before any others.

ユーザーズuser
ユーザーが使用できます。Available to any user. このグループ内のオブジェクトが最後に構築されます。Objects in this group are constructed last.

セクション-名前section-name
初期化セクションの明示的な指定を許可します。Allows explicit specification of the initialization section. ユーザー指定のセクション名のオブジェクトは暗黙的に構築されません。Objects in a user-specified section-name aren't implicitly constructed. ただし、これらのアドレスは、セクションによって名前が付けられたセクションに配置されます。However, their addresses are placed in the section named by section-name.

指定したセクション名には、そのモジュール内のプラグマの後に宣言されたグローバルオブジェクトを構築するヘルパー関数へのポインターが含まれます。The section-name you give will contain pointers to helper functions that will construct the global objects declared after the pragma in that module.

セクションを作成するときに使用しない名前の一覧については、「 /SECTION」を参照してください。For a list of names you shouldn't use when creating a section, see /SECTION.

func-名前func-name
プログラムの終了時に atexit の代わりに呼び出される関数を指定します。Specifies a function to be called in place of atexit when the program exits. また、このヘルパー関数は、グローバルオブジェクトのデストラクターへのポインターを使用して、 atexitを呼び出します。This helper function also calls atexit with a pointer to the destructor for the global object. 次の形式のプラグマで関数の識別子を指定した場合、If you specify a function identifier in the pragma of the form,

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

指定した関数が C ランタイム ライブラリの atexit の代わりに呼び出されます。then your function will be called instead of the C run-time library's atexit. これにより、オブジェクトを破棄する準備ができたときに呼び出すデストラクターのリストを作成できます。It allows you to build a list of the destructors to call when you're ready to destroy the objects.

初期化を遅延する必要がある場合 (たとえば、DLL 内で) セクション名を明示的に指定することもできます。If you need to defer initialization (for example, in a DLL) you may choose to specify the section name explicitly. コードでは、各静的オブジェクトのコンストラクターを呼び出す必要があります。Your code must then call the constructors for each static object.

atexit の代わりとなる関数は引用符で囲みません。There are no quotes around the identifier for the atexit replacement.

オブジェクトは、他のXXX_segプラグマで定義されているセクションに配置されたままになります。Your objects will still be placed in the sections defined by the other XXX_seg pragmas.

モジュールで宣言されているオブジェクトは、C ランタイムによって自動的に初期化されるわけではありません。The objects that are declared in the module aren't automatically initialized by the C run-time. コードで初期化を行う必要があります。Your code has to do the initialization.

既定では、init_seg セクションは読み取り専用です。By default, init_seg sections are read only. セクション名が.CRTの場合、コンパイラは、読み取り、書き込みとしてマークされている場合でも、属性を自動的に読み取り専用に変更します。If the section name is .CRT, the compiler silently changes the attribute to read only, even if it's marked as read, write.

翻訳単位でinit_segを複数回指定することはできません。You can't specify init_seg more than once in a translation unit.

オブジェクトが、コードで明示的に定義されたユーザー定義のコンストラクターを持っていない場合でも、コンパイラが生成することがあります。Even if your object doesn't have a user-defined constructor, one explicitly defined in code, the compiler may generate one for you. たとえば、v テーブルポインターをバインドするために1つを作成できます。For example, it may create one to bind v-table pointers. 必要に応じて、コードはコンパイラによって生成されたコンストラクターを呼び出します。When needed, your code calls the compiler-generated constructor.

Example

// 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();
}
A()
A()
A()
~A()
~A()
~A()

関連項目See also

プラグマディレクティブと __ プラグマキーワードPragma directives and the __pragma keyword