【发布时间】:2016-07-07 20:35:41
【问题描述】:
在第一个答案here中,提到了C++中的栈内存:
当一个函数被调用时,一个块被保留在栈顶用于局部变量和一些簿记数据。
考虑到this question 的上下文,这在顶层非常有意义,并且让我很好奇编译器在分配内存时的智能编译器本身是什么:因为大括号本身不是 C 中的堆栈帧 (我假设这也适用于 C++),我想检查编译器是否根据单个函数中的变量范围优化保留内存。
在下面我假设堆栈在函数调用之前看起来像这样:
--------
|main()|
-------- <- stack pointer: space above it is used for current scope
| |
| |
| |
| |
--------
然后在调用函数f()后如下:
--------
|main()|
-------- <- old stack pointer (osp)
| f() |
-------- <- stack pointer, variables will now be placed between here and osp upon reaching their declarations
| |
| |
| |
| |
--------
例如,给定这个函数
void f() {
int x = 0;
int y = 5;
int z = x + y;
}
大概,这只会分配3*sizeof(int) + 一些额外的记账开销。
但是,这个函数呢:
void g() {
for (int i = 0; i < 100000; i++) {
int x = 0;
}
{
MyObject myObject[1000];
}
{
MyObject myObject[1000];
}
}
忽略编译器优化可能会忽略上面的很多东西,因为它们实际上什么都不做,我对第二个示例中的以下内容感到好奇:
- 对于
for循环:堆栈空间是否足以容纳所有 100000 个整数? - 除此之外,堆栈空间是否会包含
1000*sizeof(MyObject)或2000*sizeof(MyObject)?
一般来说:在调用某个函数之前,编译器在确定新堆栈帧需要多少内存时是否考虑变量范围?如果这是特定于编译器的,那么一些知名的编译器是如何做到的?
【问题讨论】:
-
一对
{}是一个作用域。循环对x重复使用相同的内存,两个myObject数组不会同时存在。 -
为什么要为
100000ints分配空间,当它可以重用相同的空间时?数组也是如此。 -
编译器检查函数的每个作用域,保留的空间是所有作用域中可以同时存在的最大空间。
-
堆栈空间是预先分配的,编译器只是使用它,直到它用完并且你有溢出。
-
@n.m.同时,并非所有关于 C++ 的问题都只需要询问语言。询问编译器的实现细节,或者只是询问编译器通常如何处理语言特性的一般原则,也可以。
标签: c++ memory memory-management