全局变量何时分配内存?

时间:2011-06-28 09:50:27

标签: c++ global-variables

一段时间以来一直困扰着我,但我没有找到关于此事的任何好资源。我的代码中有一些全局变量。很明显,它们是按照某种顺序初始化的,但是在进行任何初始化之前保留所有这些对象所需的内存是什么?

这是我的代码可能出错的简单示例以及我如何使用答案:

我有一个map<RTTI, object*> objectPool,它包含我的代码中每个类的样本,我用它来加载文件中的对象。为了创建这些示例,我使用一些全局变量来将类实例引入objectPool。但有时这些示例实例是在ObjectPool本身之前初始化的。这会产生运行时错误。

要修复该错误,我使用了一些延迟初始值设定项map<RTTI,object*>* lateInitializedObjectPool;。现在每个实例首先检查objectPool是否已初始化,如果没有则初始化它,然后将其自身引入对象池。它似乎工作正常,但我担心如果对象池指针所需的内存在其他类开始自我介绍之前没有保留,这可能会导致访问冲突。

3 个答案:

答案 0 :(得分:6)

在命名空间范围内声明的变量(与类或函数相对)具有由可执行(或DLL)加载器分配的对象本身(sizeof(ObjectType))的空间。如果对象是使用聚合初始化的POD,那么它通常通过让链接器将这些值直接写入可执行文件并且exe的加载器简单地将所有这些值放入内存来获取其值。不使用聚合初始化的对象最初将其值清零。

在所有这些之后,如果这些对象中的任何一个具有构造函数,那么在 main运行之前,这些构造函数将被执行。因此,如果这些构造函数中的任何一个动态分配内存,那就是他们这样做的时候。加载可执行文件后,但在运行main之前。

答案 1 :(得分:3)

编译器通常有单独的变量存储区:

  • 最初计算出包含所有0 - 可能还有一个运行前main()构造函数来更改其内容
  • 预定具有特定的非0值,使得它们可以以预先构造的形式写入可执行图像,并且页面出现故障以备使用。

当我说“单独的存储区”时,我的意思是操作系统可执行加载程序安排进程的一些内存,就像堆栈或堆一样,但不同之处在于这些区域具有固定的预定大小。在UNIX中,上面提到的全0内存区域通常称为“BSS”,非0初始化区域称为“数据” - 有关详细信息,请参阅http://en.wikipedia.org/wiki/Data_segment

答案 2 :(得分:1)

C ++具有“静态存储持续时间”的概念。这指的是在程序执行期间占用固定空间量的各种变量。这些不仅包括全局变量,还包括命名空间,类和函数级别的static变量。

请注意,所有情况下的内存分配都可以在main之前完成,但实际的初始化会有所不同。此外,它们中的一些在正常初始化之前是零初始化的。确切地说,所有这些都是未指定的:编译器可能会添加一个隐藏的函数调用,或者操作系统恰好将过程空间归零,等等。