Sdílet prostřednictvím


init_seg

Specifické pro C++

Určuje klíčové slovo nebo oddíl kódu, který ovlivňuje pořadí spouštění spouštěcího kódu.

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

Poznámky

Významy pojmů segment a oddíl jsou v tomto tématu zaměnitelné.

Jelikož inicializace globálních statických objektů může vyžadovat spuštění kódu, je zapotřebí zadat klíčové slovo, které definuje, kdy mají být objekty vytvořeny.V dynamických knihovnách (DLL) nebo knihovnách vyžadujících inicializaci je obzvláště důležité použití direktivu pragma init_seg.

Možnosti direktivy pragma init_seg jsou následující:

  • compiler
    Vyhrazeno pro inicializaci knihoven runtime jazyka Microsoft C.Objekty v této skupině jsou vytvářeny jako první.

  • lib
    Dostupné pro inicializace dodavatelů třídních knihoven třetích stran.Objekty v této skupině jsou vytvořeny po objektech označených možností compiler, ale dříve než všechny ostatní.

  • user
    Dostupné všem uživatelům.Objekty v této skupině jsou vytvářeny jako poslední.

  • section-name
    Umožňuje explicitní určení oddílu inicializace.Objekty v uživatelem zadané skupině section-name nejsou implicitně vytvářeny. Jejich adresy jsou však umístěny do oddílu pojmenovaného možností section-name.

    Zadaný název oddílu bude obsahovat ukazatele na pomocné funkce, které vytvoří globální objekty v daném modulu za direktivou pragma.

    Seznam názvů, které by při tvorbě oddílu neměly být používány, naleznete v tématu /SECTION.

  • func-name
    Určuje funkci, která má být zavolána namísto funkce atexit při ukončení programu.Tato pomocná funkce zavolá také funkci atexit s ukazatelem na destruktor globálního objektu.Zadáte-li v direktivě pragma identifikátor funkce ve tvaru

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

    bude tato funkce zavolána namísto funkce knihovny runtime jazyka C atexit.To umožňuje sestavit seznam destruktorů, které je zapotřebí zavolat ve chvíli, kdy je vše připraveno ke zničení objektů.

Pokud je třeba odložit inicializace (například v knihovně DLL) můžete explicitně zadat název oddílu.Poté je pro každý statický objekt zapotřebí zavolat konstruktory.

Identifikátor funkce nahrazující funkci atexit není uzavřen do uvozovek.

Objekty budou stále umístěny do oddílů definovaných jinými direktivami pragma XXX_seg.

Objekty deklarované v modulu nebudou automaticky inicializovány modulem runtime jazyka C.To je zapotřebí provést svépomocí.

Ve výchozím nastavení jsou oddíly init_seg určeny jen pro čtení.Je-li název oddílu .CRT, kompilátor bez upozornění změní atribut na pouze pro čtení i v případě, že je označen jako čtení a zápis.

V jednotce překladu nelze zadat oddíl init_seg více než jednou.

I v případě, že objekt neobsahuje uživatelem definovaný konstruktor, tedy konstruktor, který není explicitně definován v kódu, může kompilátor konstruktor vygenerovat (například pro svázání ukazatelů v-table). Kód proto bude muset volat konstruktor vygenerovaný kompilátorem.

Příklad

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

Viz také

Referenční dokumentace

Direktivy Pragma a klíčové slovo __Pragma