Partager via


init_seg pragma

Spécifique À C++

Spécifie un mot clé ou une section de code qui affecte l'ordre dans lequel le code de démarrage est exécuté.

Syntaxe

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

Notes

Le segment de termes et la section ont la même signification dans cet article.

Étant donné que le code est parfois nécessaire pour initialiser des objets statiques globaux, vous devez spécifier quand construire les objets. En particulier, il est important d’utiliser les init_segpragma bibliothèques de liens dynamiques (DLL) ou dans les bibliothèques qui nécessitent une initialisation.

Les options sont init_segpragma les suivantes :

compiler
Réservé pour l'initialisation de la bibliothèque Runtime C Microsoft. Les objets de ce groupe sont construits en premier.

lib
Disponible pour les initialisations des fournisseurs de bibliothèques de classes tierces. Les objets de ce groupe sont construits après les objets marqués comme compiler, mais avant tout autre.

user
Disponible pour tout utilisateur. Les objets de ce groupe sont construits en dernier.

nom de section
Autorise la spécification explicite de la section d'initialisation. Les objets d’un nom de section spécifié par l’utilisateur ne sont pas construits implicitement. Toutefois, leurs adresses sont placées dans la section nommée par nom de section.

Le nom de section que vous donnez contient des pointeurs vers des fonctions d’assistance qui construisent les objets globaux déclarés après le pragma module.

Pour obtenir la liste des noms que vous ne devez pas utiliser lors de la création d’une section, consultez /SECTION.

func-name
Spécifie une fonction à appeler au lieu de atexit lorsque le programme se ferme. Cette fonction d’assistance appelle atexit également avec un pointeur vers le destructeur de l’objet global. Si vous spécifiez un identificateur de fonction dans le pragma formulaire,

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

votre fonctionnalité est appelée à la place de l'atexitde la bibliothèque Runtime C. Il vous permet de créer une liste des destructeurs à appeler lorsque vous êtes prêt à détruire les objets.

Si vous devez différer l'initialisation (par exemple, dans une DLL) vous pouvez choisir de spécifier le nom de section explicitement. Votre code doit ensuite appeler les constructeurs pour chaque objet statique.

Il ne reste aucun guillemet autour de l'identificateur du remplacement d'atexit.

Vos objets seront toujours placés dans les sections définies par les autres XXX_segpragma directives.

Les objets déclarés dans le module ne sont pas automatiquement initialisés par l’exécution C. Votre code doit effectuer l’initialisation.

Par défaut, les sections init_seg sont en lecture seule. Si le nom de la section est .CRT, le compilateur modifie silencieusement l’attribut en lecture seule, même s’il est marqué comme lu, écrivez.

Vous ne pouvez pas spécifier init_seg plusieurs fois dans une unité de traduction.

Même si votre objet n’a pas de constructeur défini par l’utilisateur, un constructeur explicitement défini dans le code, le compilateur peut en générer un pour vous. Par exemple, il peut en créer un pour lier des pointeurs de table v. Si nécessaire, votre code appelle le constructeur généré par le compilateur.

Exemple

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

Voir aussi

Pragma directives et mots __pragma _Pragma clés