当您请求堆栈中的空间超过可用空间时会发生什么情况
What happens when you request more space in the stack than what is available?
这个问题是基于C/C++内存分配的。
我读到了堆栈和堆之间的区别,有一件事让我很困惑。应该在堆中为大型对象分配内存,但也可以在堆栈中作为局部变量这样做。
从这个线程(程序的C/C++最大堆栈大小)中,我了解到堆栈是有限的,并且限制相对较低(最大7.4MB)。
我用以下程序测试了这个极限:
#include <vector>
int main() {
std::vector<double> test;
for (int i = 0; i < 5000000; i++){
test.push_back(i);
}
return 0;
}
分配的总内存为8字节*(5.000.000)=40MB。这似乎不会引发任何错误。我在此资源上阅读(https://software.intel.com/en-us/articles/determining-root-cause-of-sigsegv-or-sigbus-errors),堆栈溢出可能引发分段故障或总线错误。
所以我想,问题是:当你在堆栈中"分配"的内存超出你的能力时,会发生什么?
std::vector
在堆上分配内存,而不是在堆栈上。如果你想测试策略分配,最简单的方法是使用这样的程序:
#include <cstdio>
int main(void) {
char temp[1024*1024*40] = {};
printf("%sn",temp);
return 0;
}
(注意:打印是必要的,以防止缓冲区被优化掉。)
这会在堆栈上分配40 MiB,并产生堆栈溢出(请参阅实时)。
另一种方法是递归调用函数。例如:
unsigned factorial_times_2(unsigned n) {
unsigned result;
if (n<2u) result=1u;
result = n * (factorial_times_2(n-1u)/2u);
return result * 2u;
}
int main(void) {
return factorial_times_2(~0u)/2u;
}
这是对经典递归阶乘函数的简单修改(已修改,因为现代编译器会使简单阶乘尾递归)。在运行时,它将尝试制作大约40亿个堆栈帧。产生堆栈溢出(请参阅实时)。
正如您所料,堆栈溢出意味着您超出了给堆栈的内存。由于堆栈通常被分配给自己的页面,所以走出堆栈会走出有效的映射内存地址。
因此,堆栈溢出通常会导致分段错误(就像上面的例子中发生的那样)。在Windows上,这被称为访问违规。如果你运气不好,它会破坏你程序的数据,你要等到以后才能发现。
溢出堆栈的行为取决于平台。官方术语可能是"未定义的行为",意思是任何事情都可能发生。
平台不需要实现堆栈,尽管这是一种常见的技术。
有些平台为堆栈和堆留出了内存,并使它们相互"增长"(绘制一幅图)。因此,如果堆栈溢出,它就会开始在堆上进行写入,反之亦然。
一些平台可能设置了硬件围栏,当处理器访问超出范围的内存时,会生成硬件异常。操作系统将处理该异常。
另一个例子是,您的程序开始写入某种硬件设备,例如USB控制器或磁盘驱动器控制器。
总之,堆栈溢出的行为取决于平台,包括恢复(如果有的话)。
- 如何在不使用额外空间的情况下解决这个问题?
- 将指针分配给另一个指针时会发生什么情况?
- 在什么情况下,两个堆栈分配的结构对象的 this 点指向同一个地址?
- 在什么情况下,我想在 C/C++ 代码中使用内联汇编代码
- 发生注入类名时会发生什么情况?(C++)
- 在什么情况下,需要共享智能指针而无法使用唯一指针?
- 重新分配向量时,向量中的内存会发生什么情况
- 如果结构中的字符串比使用的 p/调用签名长或短,会发生什么情况?
- 为什么或在什么情况下,你会将参数作为C++中的引用(或指针)传递给函数?
- 如果我向一个12字节的缓冲区写入的字节数少于12,会发生什么情况
- 删除对象(具有不同类型)的引用时会发生什么情况?
- 如果我在 c++ 中以 new 的放置形式使用没有足够的内存,会发生什么情况?
- 使用 Google 基准测试时返回值会发生什么情况?
- 正在连接的等待条件变量的线程会发生什么情况?
- 如果未定义的C++行为符合 C 定义的行为,会发生什么情况?
- 在什么情况下,使用'const T*'输入参数比'const T&'更可取?
- 如果字符串在 C/C++ 中没有 NUL 字符(以防编译器允许它通过)会发生什么情况?
- 将虚拟方法定义为私有方法时会发生什么情况?
- 如果两个名称空间具有相同的变量名,会发生什么情况
- 当您请求堆栈中的空间超过可用空间时会发生什么情况