Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 何时在C/C+中分配静态内存+;?在编译时还是在程序运行的最开始?_C++_C_Memory_Static_Allocation - Fatal编程技术网

C++ 何时在C/C+中分配静态内存+;?在编译时还是在程序运行的最开始?

C++ 何时在C/C+中分配静态内存+;?在编译时还是在程序运行的最开始?,c++,c,memory,static,allocation,C++,C,Memory,Static,Allocation,不同的来源对我来说有不同的说法-一些StackOverflow的答案说它是在编译时分配的-其他人说它是在编译时“定义”的,并且是在运行时的一开始分配的(“加载时”是一些人所说的),而其他人说它是在编译时分配的。在C/C++中,静态内存是什么时候分配的?(如果这与“定义”变量有关——有人能告诉我在内存级别“定义”变量意味着什么吗——那将不胜感激!) 另外,在运行时如何设置指向已分配静态内存的开始的指针?静态内存的分配分两步进行 步骤1由链接器执行,因为它展示了可执行映像,并指出静态变量在相对地址空

不同的来源对我来说有不同的说法-一些StackOverflow的答案说它是在编译时分配的-其他人说它是在编译时“定义”的,并且是在运行时的一开始分配的(“加载时”是一些人所说的),而其他人说它是在编译时分配的。在C/C++中,静态内存是什么时候分配的?(如果这与“定义”变量有关——有人能告诉我在内存级别“定义”变量意味着什么吗——那将不胜感激!)


另外,在运行时如何设置指向已分配静态内存的开始的指针?

静态内存的分配分两步进行

步骤1由链接器执行,因为它展示了可执行映像,并指出静态变量在相对地址空间中的位置

当进程内存实际分配时,加载程序执行步骤2


在C++中,静态对象在进入<代码>主< /代码>之前初始化。如果您对代码不小心,您可能会看到仍然为零的对象,即使它们的构造函数总是会改变这一点。(编译器尽可能多地执行常量求值,因此玩具示例不会显示它。)

C标准只说明以下内容:

[…]所有具有静态存储持续时间的对象应在程序启动前初始化(设置为其初始值)。此类初始化的方式和时间另行规定

2对象的生存期是程序执行期间保证为其保留存储的部分。对象存在,具有恒定地址33),并在其整个生存期内保留其最后存储的值。34)如果对象在其生存期之外被引用,则行为未定义。当指针指向(或刚刚经过)的对象到达其生命周期结束时,指针的值将变得不确定

3在没有存储类说明符_Thread _local的情况下声明其标识符,并且具有外部或内部链接或存储类说明符static的对象具有静态存储持续时间。它的生命周期是程序的整个执行过程,它的存储值在程序启动之前只初始化一次

但是。。。这一点由于“似乎”规则而变得更加复杂,实际的实现只需要在可观察到的副作用范围内进行

事实上,例如在Linux中,有人可能会争辩说,具有静态存储持续时间的变量是由编译器和链接器在生成可执行文件时初始化和分配的。当程序运行时,动态链接器(
ld.so
)然后准备程序段,以便将初始化数据从可执行映像映射到内存(
mmap
),默认(零初始化)数据从零页面映射

虽然虚拟内存是由编译器、链接器和动态链接器分配的,但实际的可写RAM页面帧仅在您第一次写入页面上的变量时分配


但在基本情况下,你不需要知道这一点。就好像在输入
main
之前分配并初始化了具有静态存储持续时间的变量的内存,尽管实际情况并非如此。

在典型工具中,具有静态存储持续时间的内存按多个步骤排列:

  • 编译器在对象模块(可能通过某种形式的汇编代码)中生成数据,描述对各种内存的需求:初始化为零的内存、初始化为特定值并在此后只读的内存、初始化为特定值并可修改的内存,不需要初始化的内存,可能还有其他内存。编译器还包括必要的初始数据、有关引用所需内存中不同位置的符号的信息以及其他信息。此时,内存分配的形式大致类似于“常量数据部分需要8个字节,应将名为
    foo
    的符号设置为其地址。”
  • 链接器将此信息合并为可执行文件中的类似信息。它还解析有关符号的部分或全部信息。此时,内存分配的形式类似于“初始化的非常量数据段需要3048字节,这里是它的初始数据。当为其分配虚拟地址时,应调整以下符号:
    bar
    位于段开始的偏移124处,
    baz
    位于偏移900处…”
  • 程序加载器读取此信息,在虚拟地址空间中为其分配位置,并可将可执行文件中的一些数据读取到内存中,或在需要时通知操作系统在何处查找数据。此时,代码中引用各种符号的位置已根据这些符号的最终值进行了修改
  • 操作系统为虚拟地址分配物理内存。通常,当进程尝试访问特定页中的内存时,这是“按需”分块(内存页)完成的,而不是在程序最初加载时完成

总之,静态内存在任何特定时间都不会分配。它是许多活动的组合。对程序的影响很大程度上是,它的发生方式与程序启动时分配的方式相同,但物理内存可能仅在指令实际执行之前分配。(物理内存甚至可以从进程中取出,以后再恢复。)

当程序执行“…静态存储持续时间。对象的存储在程序开始时分配,在程序运行时释放