Dela via


init_seg pragma

C++ Specifik

Anger ett nyckelord eller kodavsnitt som påverkar i vilken ordning startkoden körs.

Syntax

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

Anmärkningar

Termerna segment och avsnitt har samma betydelse i den här artikeln.

Eftersom kod ibland krävs för att initiera globala statiska objekt måste du ange när objekten ska konstrueras. I synnerhet är det viktigt att använda init_segpragma i DLL:er (dynamic-link libraries) eller i bibliotek som kräver initiering.

Alternativen för init_segpragma är:

compiler
Reserverad för initiering av Microsoft C-körningsbibliotek. Objekt i den här gruppen skapas först.

lib
Tillgänglig för initieringar av klassbibliotek från tredje part. Objekt i den här gruppen skapas efter de objekt som har markerats som compiler, men före andra.

user
Tillgänglig för alla användare. Objekt i den här gruppen konstrueras sist.

avsnittsnamn
Tillåter explicit specifikation av initieringsavsnittet. Objekt i en användardefinerad avsnittsnamn skapas inte implicit. Adresserna placeras dock i avsnittet med namnet avsnittsnamn.

Det avsnittsnamnet du ger innehåller pekare till hjälpfunktioner som konstruerar de globala objekt som deklarerats efter pragma i modulen.

En lista med namn som du inte bör använda när du skapar ett avsnitt finns i /SECTION.

func-name
Anger en funktion som ska anropas i stället för atexit när programmet avslutas. Den här hjälpfunktionen anropar också atexit med en pekare till destruktören för det globala objektet. Om du anger en funktionsidentifierare i formulärets pragma,

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

sedan anropas funktionen i stället för C-körningsbibliotekets atexit. Det gör att du kan skapa en lista över destrukater som ska anropas när du är redo att förstöra objekten.

Om du behöver skjuta upp initieringen (till exempel i en DLL) kan du välja att uttryckligen ange avsnittsnamnet. Koden måste sedan anropa konstruktorerna för varje statiskt objekt.

Det finns inga citattecken runt identifieraren för atexit ersättning.

Objekten placeras fortfarande i de avsnitt som definieras av de andra XXX_segpragma direktiven.

Objekten som deklareras i modulen initieras inte automatiskt av C-körningen. Koden måste utföra initieringen.

Som standard är init_seg avsnitt skrivskyddade. Om avsnittsnamnet är .CRTändrar kompilatorn tyst attributet till skrivskyddat, även om det är markerat som skrivskyddat, skrivskyddat.

Du kan inte ange init_seg mer än en gång i en översättningsenhet.

Även om objektet inte har en användardefinierad konstruktor, en som uttryckligen definierats i kod, kan kompilatorn generera en åt dig. Den kan till exempel skapa en för att binda v-tabellpekare. Vid behov anropar koden den kompilatorgenererade konstruktorn.

Exempel

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

Se även

Pragma-direktiv och nyckelorden __pragma och _Pragma