init_seg
pragma
C++ 专用
指定影响启动代码的执行顺序的关键字或代码部分。
语法
#pragma init_seg(
{compiler
|lib
|user
| "section-name" [,
func-name ] })
注解
在本文中,术语“段”和“节”的含义相同。
由于有时需要代码来初始化全局静态对象,因此必须指定何时构造这些对象。 具体而言,请务必在动态链接库 (DLL) 或需要初始化的库中使用 init_seg
pragma。
init_seg
pragma 的选项包括:
compiler
保留以供 Microsoft C 运行库初始化使用. 首先构造该组中的对象。
lib
可用于第三方类库供应商的初始化。 此组中的对象在那些已标记为 compiler
的对象之后但在任何其他对象之前构造。
user
可供任何用户使用。 最后构造此组中的对象。
section-name
允许初始化部分的显式规范。 没有隐式构造用户指定的 section-name 中的对象. 但它们的地址将置于 section-name 命名的节中。
你提供的 section-name 将包含指向 helper 函数的指针,这些函数将构造在模块中的 pragma 之后声明的全局对象。
有关在创建节时不应使用的名称的列表,请参阅 /SECTION
。
func-name
指定在程序退出时为替换 atexit
而调用的函数。 此 helper 函数还调用 atexit
以及指向全局对象的析构函数的指针。 如果以 pragma 形式指定函数标识符,
int __cdecl myexit (void (__cdecl *pf)(void))
则将调用您的函数而不是 C 运行库的 atexit
。 此操作可以生成在你准备好销毁对象时要调用的析构函数的列表。
如果需要延迟初始化(例如,在 DLL 中),则可以选择显式指定节名称。 然后,你的代码必须为每个静态对象调用构造函数。
atexit
替换的标识符周围没有引号。
你的对象仍放置在由其他 XXX_seg
pragma 指令定义的节中。
模块中声明的对象不会由 C 运行时自动初始化。 代码必须执行初始化。
默认情况下,init_seg
部分是只读的。 如果节的名称是 .CRT
,编译器将在无提示的情况下将特性更改为只读,即使它被标记为读写也是如此。
不能在一个翻译单元中多次指定 init_seg
。
即使你的对象没有用户定义的构造函数(在代码中显式定义的构造函数),编译器也会生成一个构造函数。 例如,它可能会创建一个构造函数来绑定 v-表指针。 如果需要,代码将调用编译器生成的构造函数。
示例
// 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()
另请参阅
反馈
https://aka.ms/ContentUserFeedback。
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:提交和查看相关反馈