init_seg pragma

Específico do C++

Especifica uma palavra-chave ou uma seção de código que afeta a ordem na qual o código de inicialização é executado.

Sintaxe

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

Comentários

Os termos segmento e seção têm o mesmo significado neste artigo.

Como o código é necessário às vezes para inicializar objetos estáticos globais, você deve especificar quando construir os objetos. Em especial, é importante usar as init_segpragma em bibliotecas de link dinâmico (DLLs) ou em bibliotecas que exigem inicialização.

As alternativas a init_segpragma são:

compiler
Reservado para a inicialização da biblioteca em tempo de execução do Microsoft C. Os objetos nesse grupo são construídos primeiro.

lib
Disponível para as inicializações de fornecedores de bibliotecas de classes de terceiros. Os objetos nesse grupo são construídos após os marcados como compiler, mas antes de qualquer outro.

user
Disponível para qualquer usuário. Os objetos nesse grupo são construídos por último.

section-name
Permite a especificação explícita da seção de inicialização. Objetos em um section-name especificado pelo usuário não são construídos implicitamente. No entanto, os endereços deles são colocados na seção denominada section-name.

O section-name que você fornecer conterá ponteiros para funções auxiliares que construirão os objetos globais declarados nesse módulo depois do pragma.

Consulte /SECTION para obter uma lista de nomes que não devem ser usados ao criar uma seção.

func-nome
Especifique uma função a ser chamada no lugar de atexit quando o programa é encerrado. Essa função auxiliar também chamará atexit com um ponteiro para o destruidor do objeto global. Se você especificar um identificador de função no pragma do formulário,

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

a função será chamada em vez de atexit da biblioteca em tempo de execução C. Isso permite compilar uma lista dos destruidores a serem chamados quando você estiver pronto para destruir os objetos.

Se você precisar adiar a inicialização (por exemplo, em uma DLL), opte por especificar explicitamente o nome da seção. Seu código deve chamar os construtores para cada objeto estático.

Não há aspas em torno do identificador para a substituição de atexit.

Os objetos ainda serão colocados nas seções definidas pelas outras diretivas XXX_segpragma.

Os objetos que são declarados no módulo não serão inicializados automaticamente pelo tempo de execução C. Seu código precisa fazer a inicialização.

Por padrão, as seções init_seg são somente leitura. Se o nome da seção for .CRT, o compilador modificará silenciosamente o atributo como somente leitura, mesmo se estiver marcado como leitura e gravação.

Você não pode especificar init_seg mais de uma vez em uma unidade de conversão.

Mesmo se o objeto não tiver um construtor definido pelo usuário, um construtor definido explicitamente no código, o compilador poderá gerar um. Por exemplo, ele pode criar um para associar ponteiros de tabela v. Quando necessário, seu código chama o construtor gerado pelo compilador.

Exemplo

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

Confira também

Diretivas do Pragma e as palavras-chave do __pragma e _Pragma