cat*_*ood 3 c c++ memory static allocation
不同的来源对我说不同的事情 - 一些 StackOverflow 答案说它是在编译时分配的 - 其他人说它是在编译时“定义”的,并在运行时开始分配(“加载时间”是一些人所说的) ,而其他人则说它是在编译时分配的。什么时候在 C/C++ 中准确分配静态内存?(如果它与“定义”变量有关 - 有人可以告诉我在内存级别“定义”变量意味着什么 - 将不胜感激!)
另外,您将如何在运行时设置指向已分配静态内存开头的指针?
在典型的工具中,具有静态存储持续时间的内存分为多个步骤:
foo应该将调用的符号设置为它们的地址”。bar在距段开头的偏移量 124 处,baz在偏移量 900 处……”总而言之,静态内存不会在任何特定时间分配。它是许多活动的结合。对程序的影响主要在于它的发生与程序启动时所有分配的情况相同,但物理内存可能仅在指令实际执行之前分配。(物理内存甚至可以从进程中取出并在以后恢复。)
C 标准仅说明了这一点:
[...]所有具有静态存储持续时间的对象都应在程序启动前初始化(设置为其初始值)。否则未指定此类初始化的方式和时间。
和
2 对象的生命周期是程序执行期间保证为其保留存储空间的部分。一个对象存在,有一个常量地址,33) 并在其整个生命周期中保留其最后存储的值。34) 如果一个对象在其生命周期之外被引用,则行为是未定义的。当指针指向(或刚刚过去)的对象到达其生命周期结束时,指针的值变得不确定。
3 一个对象,其标识符在没有存储类说明符 _Thread_local 的情况下声明,并且具有外部或内部链接或存储类说明符 static,具有静态存储持续时间。它的生命周期是程序的整个执行过程,它的存储值在程序启动之前只初始化一次。
但是……这被as-if规则进一步复杂化,实际的实现只需要在可观察到的副作用范围内执行此操作。
事实上,例如在 Linux 中,人们可能会争辩说,具有静态存储期的变量是在生成可执行文件时由编译器和链接器初始化和分配的。当程序运行时,动态链接器 ( ld.so) 然后准备程序段,以便初始化数据mmap从可执行映像内存映射 ( ) 到 RAM,默认(零初始化)数据从零页映射。
虽然虚拟内存是由编译器、链接器和动态链接器分配的,但实际的可写 RAM 页帧仅在您第一次写入页面上的变量时才分配......
但在基本情况下您不需要了解这一点。就好像具有静态存储持续时间的变量的内存是在main进入之前分配和初始化的,即使实际情况并非如此。
静态内存分两步分配。
步骤 1 由链接器执行,因为它布置可执行映像并说明静态变量在相对地址空间中的位置。
步骤 2 由加载程序在实际分配进程内存时执行。
在 C++ 中,静态对象在进入main. 如果你不小心你的代码,你可以看到仍然为零的对象,即使它们有总是会改变它的构造函数。(编译器会尽可能多地进行常量评估,因此玩具示例不会显示它。)