何时确定使用的 c++ 程序堆栈大小? [英] when the c++ program stack size used is determined?

查看:30
本文介绍了何时确定使用的 c++ 程序堆栈大小?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道最大堆栈大小通常在链接上固定(可能在 Windows 上是这样).

I know the maximum stack size usually is fixed on link (maybe on windows is that).

但我不知道什么时候使用的程序堆栈大小(不是最大堆栈大小只是使用的大小)固定到操作系统.编译?有联系吗?执行?

But I don't know when the program stack size ( not maximum stack size just used size) used is be fixed to OS. compile ? linked ? execute ?

像这样:

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

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

the program just use 10 * sizeof(int) stack. so, is the stack size fixed?

最重要.malloc或free时堆大小是否改变?

above all. if the heap size is changed when malloc or free?

推荐答案

当程序加载时,堆栈大小没有明确提供给操作系统.相反,操作系统使用 页面错误 机制(如果 MMU 支持).

Stack size is not explicitly provided to OS, when program is loaded. Instead, OS uses mechanism of page faults (if it is supported by MMU).

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

If you try to access memory which was not granted by operating system yet, MMU generates a page fault which is handled by OS. OS checks address of page fault and either expands stack by creating new memory page or if you have exhausted stack limits, handles it as stack overflow.

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

Consider following program running on x86 and Linux:

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

int main() {
    foo();
}

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

It faults because of infinite recursion and stack overflow. It actually requires infinite stack to be completed. When program is loaded, OS allocates initial stack and writes it to %rsp (stack pointer). Let's look at foo() disassembly:

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 值.然后会产生页错误,操作系统为堆栈提供新的内存页,允许程序使用它.

After at most 4096 / 16 = 256 calls of foo(), you will break page boundary by writing a memory at address X + 4096 where X is initial %rsp value. Then page fault will be generated, and OS provide new memory page for stack, allowing program to utilize it.

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

After about 500k of foo() calls (default Linux ulimit for stack), OS will detect that application utilizes too many stack pages and send SIGSEGV to it.

这篇关于何时确定使用的 c++ 程序堆栈大小?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆