Condividi tramite


init_seg pragma

Specifiche di C++

Specifica una parola chiave o una sezione di codice che influisce sull'ordine in cui viene eseguito il codice di avvio.

Sintassi

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

Osservazioni:

I termini segmento e sezione hanno lo stesso significato in questo articolo.

Poiché il codice è talvolta necessario per inizializzare oggetti statici globali, è necessario specificare quando costruire gli oggetti. In particolare, è importante usare le init_segpragma librerie a collegamento dinamico (DLL) o nelle librerie che richiedono l'inizializzazione.

Le opzioni disponibili init_segpragma sono:

compiler
Riservato per l'inizializzazione della libreria di runtime di Microsoft C Gli oggetti in questo gruppo sono costruiti per primi.

lib
Disponibile per le inizializzazioni dei fornitori della libreria di classi di terze parti. Gli oggetti in questo gruppo vengono costruiti dopo quelli contrassegnati come compiler, ma prima di qualsiasi altro.

user
Disponibile per qualsiasi utente. Gli oggetti in questo gruppo sono costruiti per ultimi.

section-name
Consente la specifica esplicita della sezione di inizializzazione. Gli oggetti in un nome di sezione specificato dall'utente non vengono costruiti in modo implicito. Tuttavia, i relativi indirizzi vengono inseriti nella sezione denominata in base al nome della sezione.

Il nome di sezione assegnato conterrà puntatori alle funzioni helper che creeranno gli oggetti globali dichiarati dopo in pragma tale modulo.

Per un elenco di nomi che non è consigliabile usare durante la creazione di una sezione, vedere /SECTION.

func-name
Specifica una funzione da chiamare invece di atexit al termine del programma. Questa funzione helper chiama atexit anche con un puntatore al distruttore per l'oggetto globale. Se si specifica un identificatore di funzione nel pragma modulo,

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

allora la funzione verrà chiamata al posto di atexit della libreria di runtime C. Consente di compilare un elenco dei distruttori da chiamare quando si è pronti a distruggere gli oggetti.

Se si desidera posticiparne l'inizializzazione (ad esempio in una DLL) è possibile scegliere di specificare il nome della sezione in modo esplicito. Il codice deve quindi chiamare i costruttori per ogni oggetto statico.

Non ci sono virgolette che racchiudono l'identificatore per la sostituzione di atexit.

Gli oggetti verranno comunque inseriti nelle sezioni definite dalle altre XXX_segpragma direttive.

Gli oggetti dichiarati nel modulo non vengono inizializzati automaticamente dal runtime C. Il codice deve eseguire l'inizializzazione.

Per impostazione predefinita, le sezioni init_seg sono di sola lettura. Se il nome della sezione è .CRT, il compilatore modifica automaticamente l'attributo in sola lettura, anche se è contrassegnato come letto, scrivere.

Non è possibile specificare init_seg più volte in un'unità di traduzione.

Anche se l'oggetto non ha un costruttore definito dall'utente, uno definito in modo esplicito nel codice, il compilatore può generarne uno automaticamente. Ad esempio, può crearne uno per associare puntatori di tabella v. Quando necessario, il codice chiama il costruttore generato dal compilatore.

Esempio

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

Vedi anche

Pragmadirettive e parole __pragma chiave e _Pragma