在 C 和 C++ 等编程语言中,人们经常提到静态和动态内存分配.我理解这个概念,但在编译时分配(保留)所有内存"这句话总是让我感到困惑.
In programming languages like C and C++, people often refer to static and dynamic memory allocation. I understand the concept but the phrase "All memory was allocated (reserved) during compile time" always confuses me.
据我所知,编译将高级 C/C++ 代码转换为机器语言并输出一个可执行文件.如何在编译文件中分配"内存?内存不是总是在 RAM 中分配所有虚拟内存管理的东西吗?
Compilation, as I understand it, converts high level C/C++ code to machine language and outputs an executable file. How is memory "allocated" in a compiled file ? Isn't memory always allocated in the RAM with all the virtual memory management stuff ?
根据定义,内存分配不是一个运行时概念吗?
Isn't memory allocation by definition a runtime concept ?
如果我在我的 C/C++ 代码中创建一个 1KB 静态分配的变量,这会增加同样数量的可执行文件的大小吗?
If I make a 1KB statically allocated variable in my C/C++ code, will that increase the size of the executable by the same amount ?
这是在静态分配"标题下使用该短语的页面之一.
This is one of the pages where the phrase is used under the heading "Static allocation".
回归基础:内存分配,历史回顾
在编译时分配的内存意味着编译器在编译时解析某些东西将在进程内存映射中分配的地方.
Memory allocated at compile-time means the compiler resolves at compile-time where certain things will be allocated inside the process memory map.
例如,考虑一个全局数组:
For example, consider a global array:
int array[100];
编译器在编译时知道数组的大小和 int
的大小,因此它在编译时知道数组的整个大小.还有一个全局变量默认具有静态存储持续时间:它被分配在进程内存空间的静态内存区域(.data/.bss 部分).根据这些信息,编译器在编译期间决定数组将位于该静态内存区域的哪个地址.
The compiler knows at compile-time the size of the array and the size of an int
, so it knows the entire size of the array at compile-time. Also a global variable has static storage duration by default: it is allocated in the static memory area of the process memory space (.data/.bss section). Given that information, the compiler decides during compilation in what address of that static memory area the array will be.
当然,内存地址是虚拟地址.该程序假定它有自己的整个内存空间(例如从 0x00000000 到 0xFFFFFFFF).这就是为什么编译器可以做这样的假设:好吧,数组将位于地址 0x00A33211".在运行时,MMU 和操作系统将地址转换为真实/硬件地址.
值初始化静态存储的东西有点不同.例如:
Value initialized static storage things are a bit different. For example:
int array[] = { 1 , 2 , 3 , 4 };
在我们的第一个例子中,编译器只决定数组的分配位置,并将该信息存储在可执行文件中.
在值初始化的情况下,编译器还将数组的初始值注入到可执行文件中,并添加代码告诉程序加载器在程序启动时分配数组后,应该用这些值填充数组.
In our first example, the compiler only decided where the array will be allocated, storing that information in the executable.
In the case of value-initialized things, the compiler also injects the initial value of the array into the executable, and adds code which tells the program loader that after the array allocation at program start, the array should be filled with these values.
以下是编译器生成的程序集的两个示例(GCC4.8.1 with x86 target):
Here are two examples of the assembly generated by the compiler (GCC4.8.1 with x86 target):
C++ 代码:
int a[4];
int b[] = { 1 , 2 , 3 , 4 };
int main()
{}
输出汇编:
a:
.zero 16
b:
.long 1
.long 2
.long 3
.long 4
main:
pushq %rbp
movq %rsp, %rbp
movl $0, %eax
popq %rbp
ret
如您所见,这些值直接注入到程序集中.在数组a
中,编译器生成一个16字节的零初始化,因为标准说静态存储的东西默认应该初始化为零:
As you can see, the values are directly injected into the assembly. In the array a
, the compiler generates a zero initialization of 16 bytes, because the Standard says that static stored things should be initialized to zero by default:
8.5.9 (Initializers) [注意]:
每个静态存储持续时间的对象都在零初始化在任何其他初始化发生之前启动程序.在一些情况下,额外的初始化稍后完成.
8.5.9 (Initializers) [Note]:
Every object of static storage duration is zero-initialized at program startup before any other initial- ization takes place. In some cases, additional initialization is done later.
我总是建议人们反汇编他们的代码,看看编译器对 C++ 代码做了什么.这适用于从存储类/持续时间(如这个问题)到高级编译器优化.您可以指示您的编译器生成程序集,但 Internet 上有一些很棒的工具可以友好地执行此操作.我最喜欢的是 GCC Explorer.
I always suggest people to disassembly their code to see what the compiler really does with the C++ code. This applies from storage classes/duration (like this question) to advanced compiler optimizations. You could instruct your compiler to generate the assembly, but there are wonderful tools to do this on the Internet in a friendly manner. My favourite is GCC Explorer.
这篇关于“编译时分配的内存"是什么意思?实际意思?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!