C ++中用户定义类型的静态初始化

static initialization of user defined type in C++

我知道有很多关于什么是静态变量和初始化顺序的内容,这更进一步。

假设在 1 CPP 中,以下行:

struct A
{
  void* a;
  size_t b;
};

static bool bMyBoolean = true;
static std::vector<A> myVector;

这里保证bMyBooleanmyVector之前初始化。 它们也在 main() 被调用之前被初始化。
但是,myVector 具有有效值和内存地址,但在 _initterm 期间被初始化,而 bMyboolean 更早初始化并且在 initterm 期间不需要初始化调用。

这是因为它看起来是原生类型,但我找不到关于此行为的任何参考资料或信息。

一些上下文:例如,当我重载 malloc 时,并且为用户定义类型调用构造函数时,它将进入 malloc,但这里的一些静态数据不是准备好了(这是预期的,因为不能保证翻译单元之间的静态变量)但这意味着我可以安全地访问和更改它,然后它会被重新初始化。

这让我想到了下一个问题,那么这段内存存放在哪里?
它会就地重建吗?
由于正在进行 malloc 调用,因此它会被初始化。这是否意味着本机变量位于程序启动时分配的静态堆中,而用户定义的类型位于堆中?

如果是这种情况,您如何跟踪声明为静态的用户定义类型?

那是因为C++标准区分了三种类型的初始化:

  • 零初始化
  • 常量初始化
  • 动态初始化。

§ 3.6.2

  1. Variables with static storage duration or thread storage duration shall be zero-initialized before any other initialization takes place.

    Constant initialization is performed:

    • if each full-expression (including implicit conversions) that appears in the initializer of a reference with static or thread storage duration is a constant expression and the reference is bound to an lvalue designating an object with static storage duration or to a temporary
    • if an object with static or thread storage duration is initialized by a constructor call, if the constructor is a constexpr constructor, if all constructor arguments are constant expressions (including conversions), and if, after function invocation substitution, every constructor call and full-expression in the mem-initializers and in the brace-or-equal initializers for non-static data members is a constant expression
    • if an object with static or thread storage duration is not initialized by a constructor call and if every full-expression that appears in its initializer is a constant expression.

    Together, zero-initialization and constant initialization are called static initialization; all other initialization is dynamic initialization. Static initialization shall be performed before any dynamic initialization takes place.

你说的是常量初始化(静态初始化的一部分),并不局限于内置类型。

熟悉标准的 3.6.2 部分:"Initialization of non-local variables" 如果您想了解更多。


[...] but it means I can access and alter it safely, and then it gets re-initialized.

当然 - 只要 OS 允许,您随时可以修改特定内存位置下的内容。把它想象成 placement new - 为这样的对象分配了内存,但是在初始化阶段会调用构造函数。于是初始化为"in place".

Does it mean the native variables live in a static heap that is allocated at boot of the program, and the user defined types live on the heap?

没有。变量类型与其位置之间没有直接联系。局部变量放在堆栈上,动态变量(通过 malloc()/new 分配)位于堆内,静态变量位于映像内(例如 MyApp.exe)。 app执行后加载到内存中,包括所有静态存储的对象,此时预留内存。只要 main() 是 运行.

,您就可以认为此类对象有效

bMyBooleanmyVector 都存在于静态存储中,总共贡献了 sizeof(bool) + sizeof(std::vector<A>) 字节。静态存储在图像文件本身中,比如 app.exe。当您执行 app.exe 时,Windows 将图像文件加载(映射)到为新进程生成的虚拟内存地址中,这就是最初的 "dead" 静态存储开始活跃的时候。系统稍后运行 app.exe 中的代码,其中涉及在 myVector 上调用 std::vector<A> 的构造函数。即在myVector的静态存储上。还记得 this 指针吗?传递给构造函数的 this 指针将指向 myVector 的静态存储。构造函数分配的内存是动态的,并且在堆上。指向此动态存储的指针存储在 myVector.

的静态存储中

我建议您阅读有关链接和加载的更多信息。

您的 post 中有四个问题。但是,我有一种预感,您主要关心的是某些 static 对象的状态在 运行 时间环境初始化这些对象之前被 malloc 修改。

最好不要依赖全局static变量的初始化顺序。

如果malloc需要修改某些static数据,最好通过函数提供对这些数据的访问。

而不是:

static std::vector<A> myVector;

使用

static std::vector<A>& getVector()
{
   static std::vector<A> myVector;
   return myVector;
}

如果你这样做,myVector 保证在函数 returns.

时被初始化