我知道栈大小是固定的,因此我们不能在栈上存储大型对象,而需要转向动态分配内存(例如malloc)。此外,当函数调用嵌套时,栈也会被使用,因此出于这个原因,我们也避免递归函数。在运行时有没有一种方法可以确定已使用多少栈内存以及剩余多少内存?
在这里,我假设在x86体系结构下使用gcc编译器的linux环境。
我知道栈大小是固定的,因此我们不能在栈上存储大型对象,而需要转向动态分配内存(例如malloc)。此外,当函数调用嵌套时,栈也会被使用,因此出于这个原因,我们也避免递归函数。在运行时有没有一种方法可以确定已使用多少栈内存以及剩余多少内存?
在这里,我假设在x86体系结构下使用gcc编译器的linux环境。
有一个pthread API可以确定堆栈的位置:
#include <pthread.h>
void PrintStackInfo (void)
{ pthread_attr_t Attributes;
void *StackAddress;
int StackSize;
// Get the pthread attributes
memset (&Attributes, 0, sizeof (Attributes));
pthread_getattr_np (pthread_self(), &Attributes);
// From the attributes, get the stack info
pthread_attr_getstack (&Attributes, &StackAddress, &StackSize);
// Done with the attributes
pthread_attr_destroy (&Attributes);
printf ("Stack top: %p\n", StackAddress);
printf ("Stack size: %u bytes\n", StackSize);
printf ("Stack bottom: %p\n", StackAddress + StackSize);
}
仅读取%esp,并记住其值会下降。您已经从环境中知道了默认的最大大小,以及您线程的起始点。
与其他一些不可靠的编译器不同,gcc具有出色的汇编支持。
您可以通过查看/proc/<pid>/smaps
来查看堆栈虚拟内存区域的状态。当您使用更多的堆栈空间时,堆栈VMA会自动向下增长。您可以通过检查smaps
上堆栈区域的上限与%esp
的距离(因为堆栈向下增长)来检查您实际上使用了多少堆栈空间。如果使用了太多的堆栈空间,可能会首先达到由ulimit
设置的限制。
但请记住,这些底层细节可能会在没有任何通知的情况下发生变化。不要期望所有Linux内核版本和所有glibc版本都具有相同的行为。我永远不会让我的程序依赖于此信息。
这非常取决于您的操作系统及其内存管理。在Linux上,您可以使用procfs。它类似于/proc/$PID/memory。我现在不在Linux上。
GCC通常为寄存器添加16位(以跳回从中引用的函数上下文)到堆栈帧。通常,您可以通过反汇编程序来获得有关程序编译方式的更多信息。或者使用-S获取汇编代码。