init_seg
pragma
特定C++
指定會影響啟始程式碼執行順序的關鍵字或程式碼區段。
語法
#pragma init_seg(
{compiler
| |lib
user
|“section-name” [,
func-name ] })
備註
本文中的字詞 區段 和 區段 具有相同的意義。
因為有時候需要程式代碼來初始化全域靜態物件,所以您必須指定何時建構物件。 特別是,請務必在動態連結庫 (DLL) 或需要初始化的連結庫中使用 init_seg
pragma 。
選項如下 init_seg
pragma :
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_seg
pragma 指示詞所定義的區段中。
在模組中宣告的物件不會由 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()