init_seg pragma

C++-spezifisch

Gibt ein Schlüsselwort oder einen Codeabschnitt an, der sich auf die Reihenfolge auswirkt, in der Startcode ausgeführt wird.

Syntax

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

Hinweise

Die Begriffe Segment und Abschnitt haben die gleiche Bedeutung in diesem Artikel.

Da code manchmal erforderlich ist, um globale statische Objekte zu initialisieren, müssen Sie angeben, wann die Objekte erstellt werden sollen. Insbesondere ist es wichtig, die init_segpragma in Dynamic Link Libraries (DLLs) oder in Bibliotheken zu verwenden, die Initialisierung erfordern.

Folgende Optionen stehen zur init_segpragma Auswahl:

compiler
Reserviert für die Initialisierung der Microsoft C-Laufzeitbibliothek. Objekte in dieser Gruppe werden zuerst erstellt.

lib
Verfügbar für die Initialisierungen der Klassenbibliotheken von Drittanbietern. Objekte in dieser Gruppe werden nach den Objekten erstellt, die als compilergekennzeichnet sind, aber vor anderen.

user
Verfügbar für alle beliebigen Benutzer. Objekte in dieser Gruppe werden zuletzt erstellt.

Abschnittsname
Ermöglicht die explizite Angabe des Abschnitts für Initialisierung. Objekte in einem vom Benutzer angegebenen Abschnittsnamen werden nicht implizit konstruiert. Ihre Adressen werden jedoch im Abschnitt mit dem Namen des Abschnitts platziert.

Der von Ihnen angegebene Abschnittsname enthält Zeiger auf Hilfsfunktionen, die die globalen Objekte erstellen, die nach dem in diesem pragma Modul deklariert wurden.

Eine Liste der Namen, die Sie beim Erstellen eines Abschnitts nicht verwenden sollten, finden Sie unter /SECTION.

Func-Name
Gibt eine Funktion an, die statt atexit aufgerufen werden soll, wenn das Programm beendet wird. Diese Hilfsfunktion ruft atexit auch mit einem Zeiger auf den Destruktor für das globale Objekt auf. Wenn Sie einen Funktionsbezeichner im pragma Formular angeben,

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

wird die Funktion anstelle von atexit für die Laufzeitbibliothek von C aufgerufen. Sie können eine Liste der Destruktoren erstellen, die aufgerufen werden sollen, wenn Sie bereit sind, die Objekte zu zerstören.

Wenn Sie die Initialisierung verzögern müssen (z. B. in einer DLL), können Sie den Abschnittsnamen auch explizit angeben. Ihr Code muss dann die Konstruktoren für jedes statische Objekt aufrufen.

Der Bezeichner für die Ersetzung von atexit weist keine Anführungszeichen auf.

Ihre Objekte werden weiterhin in den von den anderen XXX_segpragma Direktiven definierten Abschnitten platziert.

Die im Modul deklarierten Objekte werden nicht automatisch von der C-Laufzeit initialisiert. Ihr Code muss die Initialisierung ausführen.

Standardmäßig sind init_seg-Abschnitte schreibgeschützt. Wenn der Abschnittsname lautet .CRT, ändert der Compiler das Attribut im Hintergrund schreibgeschützt, auch wenn er als gelesen markiert ist.

Sie können in einer Übersetzungseinheit nicht mehr als einmal angeben init_seg .

Auch wenn Ihr Objekt keinen benutzerdefinierten Konstruktor hat, kann der Compiler einen für Sie explizit definierten Konstruktor generieren. Beispielsweise kann es einen erstellen, um V-Tabellenzeiger zu binden. Bei Bedarf ruft ihr Code den vom Compiler generierten Konstruktor auf.

Beispiel

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

Siehe auch

Pragma-Direktiven und die __pragma und _Pragma Schlüsselwort (keyword)