init_seg pragma

C++ 特定

指定會影響啟始程式碼執行順序的關鍵字或程式碼區段。

語法

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

備註

本文中的字詞 區段 區段 具有相同的意義。

因為有時候需要程式碼來初始化全域靜態物件,所以您必須指定何時建構物件。 特別是,請務必在動態連結程式庫 (DLL) 或需要初始化的程式庫中使用 init_segpragma 。

的選項 init_segpragma 如下:

compiler
針對 Microsoft C 執行階段程式庫初始化保留。 這個群組中的物件會最先結構。

lib
可供協力廠商類別程式庫廠商進行初始化。 此群組中的物件會在標示為 compiler 的 之後建構,但在任何其他物件之前。

user
可供任何使用者使用。 這個群組中的物件會最後結構。

section-name
允許明確指定初始化區段。 不會隱含建構使用者指定 之 section-name 中的物件。 不過,其位址會放在依 section-name 命名的 區段中。

您提供給的 section-name 將包含協助程式函式的指標,這些函式會建構在該模組中宣告的 pragma 全域物件。

如需建立區段時不應該使用的名稱清單,請參閱 /SECTION

func-name
指定程式結束時,要取代 atexit 呼叫的函式。 此協助程式函式也會使用 atexit 全域物件的解構函式指標呼叫 。 如果您在 表單中 pragma 指定函式識別碼,

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

那麼將會呼叫您的函式,而不是 C 執行階段程式庫的 atexit。 它可讓您建置解構函式清單,以在準備好終結物件時呼叫。

如果您需要延遲初始化 (例如在 DLL 中),可以選擇明確指定區段名稱。 然後,您的程式碼必須呼叫每個靜態物件的建構函式。

取代 atexit 的識別項前後沒有引號。

您的物件仍會放在其他 XXX_segpragma 指示詞所定義的區段中。

在模組中宣告的物件不會由 C 執行時間自動初始化。 您的程式碼必須進行初始化。

根據預設,init_seg 區段是唯讀的。 如果區段名稱為 .CRT ,編譯器會以無訊息方式將 屬性變更為唯讀,即使它標示為讀取、寫入也一樣。

您無法在翻譯單元中指定 init_seg 一次以上。

即使您的物件沒有使用者定義的建構函式,程式碼中也明確定義一個建構函式,編譯器可能會為您產生一個。 例如,它可能會建立一個系結 v 資料表指標。 如有需要,您的程式碼會呼叫編譯器產生的建構函式。

範例

// 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()

另請參閱

Pragma 指示詞和 __pragma_Pragma 關鍵字