c++ - 使用的C++程序堆栈大小何时确定?

标签 c++ c stack

我知道最大堆栈大小通常在链接上是固定的(也许在 Windows 上就是这样)。

但我不知道所使用的程序堆栈大小(不是最大堆栈大小,只是使用的大小)何时固定到操作系统。编译?链接?执行?

像这样:

int main(){ int a[10]; return 0;}

该程序仅使用 10 * sizeof(int) 堆栈。那么,堆栈大小是固定的吗?

最重要的是。 malloc 或 free 时堆大小是否发生变化?

最佳答案

加载程序时,堆栈大小未明确提供给操作系统。相反,操作系统使用 page faults 机制(如果MMU支持的话)。

如果您尝试访问操作系统尚未授予的内存,MMU 会生成一个页面错误,该错误由操作系统处理。操作系统检查页面错误的地址,并通过创建新的内存页面来扩展堆栈,或者如果您已耗尽堆栈限制,则将其作为堆栈溢出进行处理。

考虑以下在 x86 和 Linux 上运行的程序:

void foo(void) {
    volatile int a = 10;
    foo();
}

int main() {
    foo();
}

由于无限递归和堆栈溢出而导致错误。它实际上需要无限堆栈才能完成。当程序加载时,操作系统分配初始堆栈并将其写入%rsp(堆栈指针)。让我们看一下 foo() 反汇编:

push   %rbp
mov    %rsp,%rbp         <--- Save stackpointer to %rbp
sub    $0x10,%rsp        <--- Advance stack pointer by 16 bytes
movl   $0xa,-0x4(%rbp)   <--- Write memory at %rbp
callq  0x400500 <foo>
leaveq 
retq 

在最多 4096/16 = 256 次 foo() 调用之后,您将通过在地址 X + 4096 处写入内存来打破页边界,其中 X 是初始值 %rsp 值。然后就会产生页面错误,操作系统为堆栈提供新的内存页面,允许程序使用它。

在大约 500k 次 foo() 调用(默认的 Linux ulimit 堆栈)之后,操作系统将检测到应用程序使用了过多的堆栈页面并向其发送 SIGSEGV。

关于c++ - 使用的C++程序堆栈大小何时确定?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29960754/

相关文章:

c++ - 为什么这个简单的 C++ 代码不能编译?

c - 如何实现具有多元素结构的链表?

c++ - 删除带有堆栈的二叉树

c++ - 是否可以更改C/C++中自动变量的分配区域?

java - 逆波兰计算器未返回正确的值

c++ - 在 C++ 中将字节字符串转换为普通字符串

c++指向函数的指针作为参数

c++ - 卸载时XAudio2访问冲突异常

C 扩展 : <? 和 >?运营商

c - qsort 没有正确排序结构