init_seg pragma

Específico de C++

Especifica una palabra clave o una sección de código que afecta al orden en que se ejecuta el código de inicio.

Sintaxis

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

Comentarios

Los términos segmento y sección tienen el mismo significado en este artículo.

Dado que a veces se requiere código para inicializar objetos estáticos globales, debe especificar cuándo se deben construir los objetos. En concreto, es importante usar init_segpragma en bibliotecas de vínculos dinámicos (DLL) o en bibliotecas que requieren inicialización.

Las opciones para init_segpragma son:

compiler
Reservada para la inicialización de la biblioteca en tiempo de ejecución de C de Microsoft. Los objetos de este grupo se construyen en primer lugar.

lib
Disponible para las inicializaciones de los proveedores de bibliotecas de clases de terceros. Los objetos de este grupo se construyen después de los marcados como compiler, pero antes que cualquier otro.

user
Disponible para cualquier usuario. Los objetos de este grupo se construyen en último lugar.

section-name
Permite la especificación explícita de la sección de inicialización. Los objetos de un section-name especificado por el usuario no se construyen implícitamente. Sin embargo, sus direcciones se colocan en la sección denominada por section-name.

El section-name que asigne contendrá punteros a funciones del asistente que construirán los objetos globales declarados en ese módulo después de pragma.

Para obtener una lista de los nombres que no debe utilizar cuando cree una sección, consulte /SECTION.

func-name
Especifica la función que se va a llamar en lugar de atexit cuando termine el programa. Esta función del asistente también llama a atexit con un puntero al destructor del objeto global. Si especifica un identificador de función en pragma con el formato,

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

se llamará a su función en lugar de a atexit de la biblioteca en tiempo de ejecución de C. Permite crear una lista de los destructores a los que llamar cuando esté listo para destruir los objetos.

Si necesita diferir la inicialización (por ejemplo, en una DLL), puede elegir especificar el nombre de sección explícitamente. En tal caso, su código deberá llamar a los constructores de cada objeto estático.

No se incluyen comillas alrededor del identificador del sustituto de atexit.

Sus objetos se incluirán igualmente en las secciones definidas por las otras directivas XXX_segpragma.

El motor de tiempo de ejecución de C no inicializan automáticamente los objetos que se declaren en el módulo. El código tiene que realizar la inicialización.

De forma predeterminada, las secciones init_seg son de solo lectura. Si el nombre de sección es .CRT, el compilador cambia silenciosamente el atributo a de solo lectura, aunque esté marcado como de lectura o escritura.

No puede especificar init_seg más de una vez en una unidad de traducción.

Aunque el objeto no tenga un constructor definido por el usuario (uno definido explícitamente en el código), el compilador puede generar uno automáticamente por usted. Por ejemplo, puede crear uno para enlazar punteros de tabla virtual. Cuando sea necesario, el código llama al constructor generado por el compilador.

Ejemplo

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

Consulte también

Directivas pragma y las palabras clave __pragma y _Pragma