init_seg
pragma
Специфика C++
Определяет ключевое слово или раздел кода, влияющие на порядок выполнения кода запуска.
Синтаксис
#pragma init_seg(
{ |compiler
|lib
|user
"section-name" [,
func-name ] })
Замечания
Сегмент терминов и раздел имеют то же значение в этой статье.
Так как код иногда требуется для инициализации глобальных статических объектов, необходимо указать, когда создавать объекты. В частности, важно использовать init_seg
pragma библиотеки динамического канала (БИБЛИОТЕКи DLL) или библиотеки, требующие инициализации.
Ниже приведены следующие параметры init_seg
pragma :
compiler
Зарезервирован для инициализации библиотеки времени выполнения Microsoft C. Объекты в этой группе создаются первыми.
lib
Доступен для инициализаций поставщиков сторонних библиотек классов. Объекты в этой группе создаются после того, как они помечены как compiler
другие.
user
Доступен для любого пользователя. Объекты в этой группе создаются последними.
имя раздела
Позволяет явно определить раздел инициализации. Объекты в указанном пользователем имени раздела не создаются неявно. Однако их адреса помещаются в раздел с именем раздела.
Имя раздела , которое будет содержать указатели на вспомогательные функции, которые будут создавать глобальные объекты, объявленные после pragma этого модуля.
Список имен, которые не следует использовать при создании раздела, см. в разделе /SECTION
.
func-name
Определяет функцию, вызываемую вместо функции atexit
при выходе из программы. Эта вспомогательной функции также вызывает atexit
указатель на деструктор глобального объекта. Если указать идентификатор функции в pragma форме,
int __cdecl myexit (void (__cdecl *pf)(void))
то вместо функции atexit
библиотеки времени выполнения C будет вызываться пользовательская функция. Он позволяет создать список деструкторов для вызова, когда вы будете готовы к уничтожению объектов.
Если требуется отложить инициализацию (например, в библиотеке DLL), можно явно указать имя раздела. Затем код должен вызывать конструкторы для каждого статического объекта.
Идентификатор для замены функции atexit
не заключается в кавычки.
Объекты по-прежнему будут помещены в разделы, определенные другими XXX_seg
pragma директивами.
Объекты, объявленные в модуле, не инициализированы автоматически во время выполнения C. Код должен выполнять инициализацию.
По умолчанию разделы init_seg
предназначены только для чтения. Если имя раздела равно .CRT
, компилятор автоматически изменяет атрибут только для чтения, даже если он помечен как чтение, запись.
Невозможно указать init_seg
несколько раз в единице перевода.
Даже если у объекта нет определяемого пользователем конструктора, один явно определенный в коде, компилятор может создать его для вас. Например, он может создать один для привязки указателей v-table. При необходимости код вызывает созданный компилятором конструктор.
Пример
// 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()