为调用堆栈分配了多少内存?
How much memory is allocated to call stack?
以前看过很多C++函数的汇编。在 gcc 中,它们都以这些指令开头:
push rbp
mov rbp, rsp
sub rsp, <X> ; <X> is size of frame
我知道这些指令存储前一个函数的帧指针,然后为当前函数设置一个帧。但是在这里,程序集既不要求映射内存(如 malloc),也不检查 rbp
指向的内存是否已分配给进程。
因此它假定启动代码已为整个调用堆栈深度映射了足够的内存。那么究竟为调用栈分配了多少内存呢?启动代码如何知道调用堆栈的最大深度?
这也意味着,我可以越界远距离访问数组,因为虽然它不在当前帧中,但它映射到进程。所以我写了这段代码:
int main() {
int arr[3] = {};
printf("%d", arr[900]);
}
当索引为 900 时,这将以 SIGSEGV
退出。但令人惊讶的是,当索引为 901 时,它不会以 SIGSEGV
退出。同样,对于某些随机索引,它会以 SIGSEGV
退出,而对于某些随机索引则不会。在 compiler explorer.
中使用 gcc-x86-64-11.2 编译时观察到此行为
How does startup code can know the maximum depth of call stack?
没有。
在最常见的实现中,堆栈的大小是恒定的。
如果程序超出常量大小的堆栈,则称为堆栈溢出。这就是为什么你必须避免在自动存储中创建大对象(通常但不一定是数组),以及为什么你必须避免具有线性深度的递归(例如递归链表算法)。
So exactly how much memory is allocated for call stack?
在大多数 desktop/server 系统上,它是可配置的,默认为一到几兆字节。在嵌入式系统上它可以少得多。
This is exiting with SIGSEGV when index is 900. But surprisingly not when index is 901.
在这两种情况下,程序的行为都是未定义的。
Is it possible to know the allocated stack size?
是的。您可以阅读目标系统的文档。如果您打算编写一个可移植程序,那么您必须假定所有目标系统中的最小值。对于desktop/server,我提到的1MB是合理的。
C++ 中没有标准 获取大小的方法。
以前看过很多C++函数的汇编。在 gcc 中,它们都以这些指令开头:
push rbp
mov rbp, rsp
sub rsp, <X> ; <X> is size of frame
我知道这些指令存储前一个函数的帧指针,然后为当前函数设置一个帧。但是在这里,程序集既不要求映射内存(如 malloc),也不检查 rbp
指向的内存是否已分配给进程。
因此它假定启动代码已为整个调用堆栈深度映射了足够的内存。那么究竟为调用栈分配了多少内存呢?启动代码如何知道调用堆栈的最大深度?
这也意味着,我可以越界远距离访问数组,因为虽然它不在当前帧中,但它映射到进程。所以我写了这段代码:
int main() {
int arr[3] = {};
printf("%d", arr[900]);
}
当索引为 900 时,这将以 SIGSEGV
退出。但令人惊讶的是,当索引为 901 时,它不会以 SIGSEGV
退出。同样,对于某些随机索引,它会以 SIGSEGV
退出,而对于某些随机索引则不会。在 compiler explorer.
How does startup code can know the maximum depth of call stack?
没有。
在最常见的实现中,堆栈的大小是恒定的。
如果程序超出常量大小的堆栈,则称为堆栈溢出。这就是为什么你必须避免在自动存储中创建大对象(通常但不一定是数组),以及为什么你必须避免具有线性深度的递归(例如递归链表算法)。
So exactly how much memory is allocated for call stack?
在大多数 desktop/server 系统上,它是可配置的,默认为一到几兆字节。在嵌入式系统上它可以少得多。
This is exiting with SIGSEGV when index is 900. But surprisingly not when index is 901.
在这两种情况下,程序的行为都是未定义的。
Is it possible to know the allocated stack size?
是的。您可以阅读目标系统的文档。如果您打算编写一个可移植程序,那么您必须假定所有目标系统中的最小值。对于desktop/server,我提到的1MB是合理的。
C++ 中没有标准 获取大小的方法。