各程序是否分配固定栈大小?运行中应用的栈内存容量由谁定义?
程序栈内存分配常见问题解答
1. 运行代码时,编译器是否会在编译后“检测”出所需的Stack内存容量,从而为每个程序分配专属的栈内存块?
不会。编译器仅能在编译阶段确定单个函数的栈帧大小,包括函数内部定义的局部变量总占用空间、栈帧保存返回地址、栈基址寄存器所需的固定开销等,但无法预测程序运行全程的总栈内存用量:比如递归调用的深度、动态的函数调用链路都是运行时才能确定的,编译器不可能提前算出整个程序的最大栈需求。
此外栈内存的分配是程序被加载到内存运行时由操作系统/加载器完成的,不属于编译阶段的工作,编译器不会在编译后为程序分配栈内存块。
2. 各程序的栈内存容量是否由OS定义?
操作系统会给出栈容量的默认上限值,比如32位/64位Linux系统默认用户进程栈上限为8MB,Windows系统默认栈上限为1MB,这个默认值确实是操作系统层面预先定义的,但它只是基础参考值,不是最终的实际生效值。
3. 实际运行的各应用的栈内存容量究竟由谁定义?
实际生效的栈容量上限由三层规则共同决定,优先级从低到高如下:
- 第一层是操作系统的全局默认栈上限
- 第二层是可执行文件的编译链接配置:Windows下用Visual Studio编译时可通过
/STACK链接选项自定义栈的保留和提交大小,Linux下用ld链接时可通过--stack参数修改默认栈上限,配置会写入PE/ELF可执行文件的头部字段 - 第三层是运行时的资源限制配置:比如Linux下可通过
ulimit -s命令调整当前shell会话启动的程序的栈上限,优先级高于可执行文件内的配置;多线程程序创建子线程时,还可以通过pthread_attr_setstacksize这类API单独指定单个线程的栈大小,不受进程默认栈上限约束。
4. 是否不存在上述限制,程序可按需占用全部栈内存?
栈内存有严格的用量上限,不可能无限制占用。一旦程序运行时的栈使用量超过当前生效的上限,会触发栈溢出错误,操作系统会直接发送段错误信号(Linux下SIGSEGV)或抛出栈溢出异常(Windows下STATUS_STACK_OVERFLOW)终止程序运行。即便系统还有大量空闲内存,只要栈用量超出提前设定的上限,就会触发崩溃。
内容的提问来源于stack exchange,提问作者Vitor de oliveira
相关产品推荐
相关产品推荐

