init_seg
C + + 特定
指定的關鍵字或程式碼區段會影響程式碼會執行在哪一個啟動的順序。
#pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )
備註
詞彙的意義區段 和 一節能互相對換本主題中。
因為初始化的全域靜態物件可能包含執行程式碼,您必須指定定義物件時若要建構的關鍵字。它是特別重要而必須使用 init_seg pragma,在動態連結程式庫 (Dll) 或程式庫需要初始化。
此選項以 init_seg pragma 是:
編譯器
保留對 Microsoft C run-time 程式庫初始化。第一次建構這個群組中的物件。lib
可用的類別程式庫第三方廠商的初始設定。這個群組中的物件建構後那些標記為編譯器但再執行其他。User - 使用者
任何使用者可以使用。上一次建構這個群組中的物件。區段名稱
容許明確指定 [初始化] 區段。在 [使用者指定的物件區段名稱不隱含建構。 不過,將他們的地址放在區段中藉由名為區段名稱。這個區段名稱就會包含將建構 pragma 之後,該模組中宣告的全域物件的 helper 函式的指標。
如需建立區段時,應該不會使用您的名稱的清單,請參閱 /SECTION。
函式名稱
指定所要的位置呼叫函式atexit關閉程式。此 helper 函式也會呼叫 atexit 與全域物件的解構函式的指標。如果您在表單中的 pragma 指定函式的識別項int __cdecl myexit (void (__cdecl *pf)(void))
接著會呼叫您的函式,而不是 c 執行階段程式庫的atexit。這可讓您建立一份將需要被呼叫,當您準備好要終結的物件的解構函式。
如果您需要盡量延後 (例如,在為 DLL) 的初始設定,您可以選擇明確指定的區段名稱。然後,您就必須為每個靜態物件呼叫建構函式。
有沒有引號的識別項atexit取代。
您的物件仍被置於其他的 XXX_seg pragma 所定義的區段。
由 c 執行階段將不會自動初始化在模組中宣告的物件。您必須在該自己動手。
預設情況下, init_seg節唯讀的。如果區段名稱。CRT,編譯器會以無訊息模式變更的屬性為唯讀,即使它標示為已讀取,寫入。
您不能指定 init_seg 不止一次的轉譯單位中。
即使您的物件沒有建構使用者定義函式,建構函式未明確定義在程式碼,編譯器可能會產生一個 (例如繫結 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();
}