问题是关于Linux如何处理堆栈。为什么当我运行此代码时遇到分段错误时不确定?
#include <stdio.h>
#include <stdlib.h>
#include <sys/resource.h>
void step(int n) {
printf("#%dn", n);
step(n + 1);
}
int main() {
step(1);
return 0;
}
看起来非确定性结果是内核在启动新程序时使用的环境随机化策略的结果。让我们尝试下一个代码:
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
int main(int argc, char **argv) {
char c;
uintptr_t addr = (uintptr_t)&c;
unsigned pagesize = (unsigned)sysconf(_SC_PAGE_SIZE);
printf("in-page offset: %un", (unsigned)(addr % pagesize));
return 0;
}
在我的 64 位 Linux 上,它给出了下一个输出:
$ ./a.out
in-page offset: 3247
$ ./a.out
in-page offset: 2063
$ ./a.out
in-page offset: 863
$ ./a.out
in-page offset: 1871
每次c
在其堆栈页面中获得新的偏移量时,并且知道内核总是为堆栈分配离散数量的页面 - 很容易看出每次程序分配的堆栈数量略有不同。因此,问题中描述的程序在每次调用时都有非恒定的帧堆栈量。
坦率地说,我不确定是内核调整堆栈指针的初始值,还是动态链接器的一些技巧。无论如何 - 用户代码每次都会在随机环境中运行。
因为堆栈溢出是未定义的行为。实现可以自由测试它不会发生,在这种情况下,当堆栈已满时,程序应以错误结束。但环境也可以提供一个堆栈,其大小取决于可用内存。或者更有可能的是,您可能会在与io系统交互时遇到各种内存覆盖问题,这可能是非确定性的。或。。。(本质上,UB意味着任何事情都可能发生(。