Megosztás:


init_seg pragma

C++ specifikus

Olyan kulcsszó- vagy kódszakaszt ad meg, amely befolyásolja az indítási kód végrehajtásának sorrendjét.

Szintaxis

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

Megjegyzések

A szegmensek és szakasz azonos jelentéssel bírnak ebben a cikkben.

Mivel a globális statikus objektumok inicializálásához néha kódra van szükség, meg kell adnia, hogy mikor kell létrehozni az objektumokat. Különösen fontos, hogy a init_segpragma dinamikus csatolású kódtárakban (DLL-ekben) vagy inicializálást igénylő kódtárakban használják.

A init_segpragma a következő lehetőségek közül választhat:

compiler
A Microsoft C futásidejű kódtár inicializálásához van fenntartva. A csoport objektumai először létre lesznek építve.

lib
Harmadik fél osztálykódtár-beszállítói inicializálásához érhető el. Az ebben a csoportban lévő objektumok a compiler, de a többi előtt vannak létrehozva.

user
Bármely felhasználó számára elérhető. A csoport objektumai az utolsóként jönnek létre.

szakasznév
Engedélyezi az inicializálási szakasz explicit specifikációját. A felhasználó által megadott szakasznév objektumai nem implicit módon lesznek létrehozva. A címek azonban a szakasznéváltal elnevezett szakaszba kerülnek.

A megadott szakasznév olyan segédfüggvények mutatóit tartalmazza, amelyek a modul pragma után deklarált globális objektumokat fogják létrehozni.

A szakasz létrehozásakor nem használandó nevek listáját a /SECTIONcímű témakörben találja.

func-name
Olyan függvényt ad meg, amelyet atexit helyett kell meghívni, amikor a program kilép. Ez a segédfüggvény a globális objektum destruktorára mutató mutatóval is meghívja atexit. Ha függvényazonosítót ad meg az űrlap pragma,

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

akkor a függvény a C futásidejű kódtár atexithelyett lesz meghívva. Ez lehetővé teszi a destruktorok listájának összeállítását, ha készen áll az objektumok elpusztítására.

Ha el kell halasztania az inicializálást (például egy DLL-ben), dönthet úgy, hogy explicit módon adja meg a szakasz nevét. A kódnak ezután meg kell hívnia az egyes statikus objektumok konstruktorait.

A atexit csere azonosítója körül nincsenek idézőjelek.

Az objektumok továbbra is a többi XXX_segpragma irányelvek által meghatározott szakaszokban lesznek elhelyezve.

A modulban deklarált objektumokat a C futási idő nem inicializálja automatikusan. A kódnak el kell végeznie az inicializálást.

Alapértelmezés szerint init_seg szakaszok csak olvashatók. Ha a szakasz neve .CRT, a fordító csendben csak olvasásra módosítja az attribútumot, még akkor is, ha olvasottként van megjelölve, írjon.

A fordítási egységben nem adhat meg többször init_seg.

A fordító akkor is létrehozhat egyet, ha az objektum nem rendelkezik felhasználó által definiált konstruktorsal, amely kifejezetten kódban van definiálva. Létrehozhat például egyet a v-table mutatóinak kötéséhez. Szükség esetén a kód meghívja a fordító által létrehozott konstruktort.

Példa

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

Lásd még:

Pragma irányelvei, valamint a __pragma és _Pragma kulcsszavak