注:此问题与x86_64体系结构和Linux ABI有关。
启动程序时,会为堆栈分配一些空间。稍后,在程序执行期间,可以调整堆栈区域的大小(需要更多空间时),直到操作系统指定的最大值。
以简单程序为例:
int main() {
char bytes[7 * 1024 * 1024];
}
让我们在gdb下运行它并设置断点:在main之前和在声明数组之后。
gdb> b *main
gdb> b main
gdb> r
gdb> info proc mapping // breakpoint before pushing stack
Start Addr End Addr Size Offset objfile
0x7ffffffde000 0x7ffffffff000 0x21000 0x0 [stack]
gdb> c
gdb> info proc mapping // breakpoint after pushing stack
Start Addr End Addr Size Offset objfile
0x7fffff8fe000 0x7ffffffff000 0x701000 0x0 [stack]
所以我们可以看到堆栈实际上已调整大小。
问题是操作系统如何知道何时需要调整堆栈大小?。一些互联网资源表示OS处理page fault exception
,如果访问的地址在可能的堆栈地址范围内,则会对其进行调整大小。
但是当我逐步调试程序时,结果是,按照以下说明调整了堆栈的大小:
0x40129d <main+4> sub rsp, 0x700010
所以(据我所知),由于我们实际上并未访问地址,因此还没有page fault
。我们只更改rsp
寄存器。那么操作系统如何处理呢?还是在更改page fault exception
之后有一个rsp
?
操作系统如何处理它?还是在更改rsp之后出现页面错误异常?
您看到的“堆栈增长”不是由操作系统生成的,而是由gdb本身计算的(例如从rsp
到堆栈末尾的距离。