init_seg
Określonego język C++
Określa słowo kluczowe lub sekcję kodu, która ma wpływ na kolejność, w której wykonywany jest kod startowy.
#pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )
Uwagi
Terminy segment i sekcja stosowane są zamiennie w tym temacie.
Ponieważ inicjowanie statycznych obiektów globalnych może obejmować wykonanie kodu, należy określić słowo kluczowe, które określa, kiedy obiekty mają być zbudowane.To szczególnie ważne, aby użyć dyrektywy init_seg w bibliotekach dołączanych dynamicznie (dll) lub wymagających inicjowania.
Opcje dyrektywy init_seg są następujące:
compiler
Zarezerwowana do inicjowania biblioteki wykonawczej Microsoft C.Obiekty z tej grupy są budowane na początku.lib
Dostępna do inicjalizacji biblioteki klas innych dostawców.Obiekty z tej grupy są budowane po tych oznaczonych jako compiler, ale przed wszystkimi innymi.user
Dostępne dla każdego użytkownika.Obiekty z tej grupy są budowane na końcu.section-name
Umożliwia jawne określenie sekcji inicjalizacji.Obiekty w określonej przez użytkownika section-name nie są niejawnie konstruowane; Jednakże ich adresy są umieszczane w sekcji o nazwie section-name.Sekcja o podanej nazwie będzie przechowywać wskaźniki na funkcje pomocnicze, które będą budować obiekty globalne zadeklarowane w module po dyrektywie.
Aby uzyskać listę nazw których nie wolno używać podczas tworzenia sekcji, zobacz /SECTION.
func-name
Określa funkcję, która ma być wywoływana zamiast atexit podczas zamykania programu.Funkcja pomocnicza wywołuje również atexit ze wskaźnikiem do destruktora dla obiektu globalnego.Jeśli identyfikator funkcji zostanie podany w dyrektywie formularza,int __cdecl myexit (void (__cdecl *pf)(void))
to wtedy zamiast funkcji atexit z biblioteki wykonawczej C zostanie wywołana funkcja użytkownika.Dzięki temu można zbudować listy destruktorów, które będą musiały zostać wywołane, gdy trzeba będzie zniszczyć obiekty.
Jeśli trzeba opóźnić inicjalizację (na przykład w bibliotece DLL) można jawnie określić nazwę sekcji.Następnie należy wywołać konstruktory dla każdego obiektu statycznego.
Nie ma cudzysłowu wokół identyfikatora zamiennika funkcji atexit.
Obiekty będą nadal umieszczone w sekcjach określonych przez inne dyrektywy XXX_seg.
Obiekty, które są zadeklarowane w module nie zostaną automatycznie zainicjowane w czasie wykonania.Trzeba będzie zrobić to ręcznie.
Domyślnie sekcje init_seg są tylko do odczytu.Jeśli nazwy sekcji to .CRT, kompilator dyskretnie zmieni ten atrybut na tylko do odczytu, nawet jeśli jest oznaczony jako możliwy do odczytu i pisania.
Nie można określić init_seg więcej niż jeden raz w jednostce translacji.
Nawet jeśli obiekt nie ma konstruktora zdefiniowanego przez użytkownika, konstruktora nie zdefiniowanego jawnie w kodzie, kompilator może wygenerować taki konstruktor (na przykład aby powiązać wskaźniki tabeli v-table). Kod będzie więc musiał wywołać konstruktor generowany przez kompilator.
Przykład
// 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();
}