Partager via


init_seg

Détail C++

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

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

Notes

La signification des termes segment et section sont interchangeable dans cette rubrique.

Étant donné que l'initialisation des objets statiques globales peut impliquer exécuter du code, vous devez spécifier un mot clé qui définit lorsque les objets doivent être construits.Il est particulièrement important d'utiliser le pragma d' init_seg aux bibliothèques de liens (DLLs) dynamiques ou bibliothèques qui ont besoin d'initialisation.

les options au pragma d' init_seg sont :

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

  • lib
    disponible pour les initialisations des tiers fournisseurs de bibliothèque de classes.Les objets à ce groupe sont construits après ceux qui sont marqués comme compilateur mais avant les autres.

  • utilisateur
    Disponible pour tout utilisateur.Les objets à ce groupe sont conçus pour la dernière fois.

  • nom de la 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 implicitement construits ; toutefois, leurs adresses sont placées dans la section nommée par nom de section.

    Le nom de section que vous donnez contiendra les pointeurs vers des fonctions d'assistance qui construiront les objets globaux déclarés dans ce module après le pragma.

    Pour une liste des noms que vous ne devez pas utiliser lorsque vous créez une section, consultez /SECTION.

  • fonctionnel-nom
    Spécifie une fonction à appeler au lieu d' atexit lorsque le programme se ferme.Cette fonction d'assistance appelle également atexit avec un pointeur vers le destructeur de l'objet global.si vous spécifiez un identificateur de fonction dans le pragma du formulaire,

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

    votre fonction sera appelée au lieu d' atexitde la bibliothèque runtime C.Cela vous permet de générer une liste des destructeurs qui devront être appelés lorsque vous êtes prêt à détruire des objets.

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

Il n'existe aucun guillemet autour de l'identificateur pour le remplacement d' atexit .

Vos objets seront toujours placés dans les sections définies par les autres pragmas de XXX_seg.

Les objets déclarés dans le module ne seront pas automatiquement initialisés par le runtime C.Vous devez effectuer que vous-même.

Par défaut, des sections d' init_seg sont lues uniquement.Si le nom de la section .CRT est, le compilateur modifie silencieusement l'attribut pour indiquer que, même s'il est marqué comme lu, entrez.

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 non définie explicitement dans le code, le compilateur peut générer un (par exemple pour lier des pointeurs de v-tableau).Par conséquent, votre code doit appeler 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();
}
  

Voir aussi

Référence

Directives pragma et le mot clé de __Pragma