对于以下代码,最后一个输出(最大堆栈深度不断变化):
#include <stdio.h>
#include <windows.h>
int depth=0;
void func(){
int x=depth;
printf("%d\n",depth++);
func();
printf("%d\n",x);
}
int main(){
func();
return 0;
}
//由
cl /F 1 test.c
编译第一次是
3717
,第二个是3700
,第三个是3695
.我认为对于恒定的堆栈大小,最大堆栈深度应该是恒定的。但为什么会发生变化?
最佳答案
在运行 x86/x64 CPU 的 Microsoft Windows 平台上,为堆栈保留的内存总是以 page 结尾。边界和stack overflow当堆栈增长超出该页面边界时将发生。一页通常是 4096 字节的内存。
无 Address Space Layout Randomization (ASLR),堆栈也将从页面边界开始,这意味着最大堆栈大小将是页面大小的倍数。默认情况下,堆栈的最大大小为 1 MiB , 即 256 页 4096 字节。
但是,当 ASLR 处于事件状态时,堆栈的起始地址不再位于页面边界上,而是随机的。由于为堆栈保留的内存仍以页面边界结束,这意味着最大堆栈大小是随机的,不再是页面大小的倍数。
最大堆栈大小的这种随机性就是堆栈溢出的时间也是随机的原因。
默认情况下,Microsoft 链接器在启用 ASLR 的情况下构建可执行文件。为了禁用 ASLR,您必须添加 /DYNAMICBASE:NO
调用链接器时的选项。之后,无论何时运行程序,堆栈溢出都应该在完全相同的时间发生。
关于c - 为什么最大堆栈深度不断变化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60693620/