init_seg

C++ 特定

指定顺序将影响启动代码执行的关键字或代码部分。

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

备注

术语 段 和 部分的 含义可互换本主题。

因为全局静态对象的初始化可能涉及执行代码,必须指定定义的关键字对象时将构造。 在需要初始化的动态链接库或库中使用 init_seg 说明 (DLLs)尤其重要。

init_seg 批注的选项是:

  • 编译器
    对于 Microsoft C 运行库初始化保留。 对象该组中首先构造。

  • lib
    可用于第三方类库供应商的初始化。 对象该组中的中任何之前已标记为 编译器 ,但这些之后构造。

  • User — 用户
    可供任何用户。 对象该组中最后一个构造。

  • 节名称
    允许初始化部分的显式指定。 在用户指定的 节名称的 对象未隐式构造;但是,它们的地址在 节的名称命名的节放置。

    您为的节名称将包含指向将构造该模块声明的全局对象在注释后的 helper 函数。

    有关何时不应使用创建部分名称的列表,请参见 /SECTION

  • 函数名称
    ,在程序退出时,指定在 atexit 位置将调用的函数。 此帮助器函数也称为 " 于指针的 atexit 到全局对象的析构函数。 如果您在窗体上指定批注函数标识符,

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

    然后将函数调用而不是 C 运行库的 atexit。 这使您可以生成需要调用析构函数的列表,当您准备销毁对象时。

如果需要延迟初始化 (例如,在 DLL) 可以选择显式指定该节的名称。 然后必须对每个静态对象的构造函数。

边不 atexit 替换的标识符附近。

对象在其他 XXX_seg 说明定义的部分上。

在模块中声明的对象不会在 C 运行时自动初始化。 您需要进行您。

默认情况下, init_seg 部分只读。 如果该节的名称是 .CRT,编译器将无提示地更改属性是只读的,因此,即使它标记为读取,编写。

在翻译单元不能多次指定 init_seg

即使对象没有用户定义的构造函数,代码中没有显式定义构造函数,编译器可能生成一 (例如将 hyper-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();
}
  

请参见

参考

杂注指令和__Pragma关键字