我知道堆栈大小是固定的。所以我们不能在堆栈上存储大对象,我们转向动态分配(例如malloc)。此外,当存在函数调用嵌套时使用堆栈,因此我们也避免了递归函数。在运行时有没有办法确定到目前为止使用了多少堆栈内存以及剩下多少?
在这里,我假设使用x86架构的linux环境(gcc编译器)。
答案 0 :(得分:5)
有一个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);
}
在i386上,堆栈从底部开始并向顶部增长。
所以你知道你有($ ESP - StackAddress)字节可用。
在我的系统中,我有一个pthread_create()的包装器,所以每个线程都在我的私有函数中启动。在那个函数中,我找到了如上所述的堆栈,然后找到未使用的部分,然后用一个独特的模式初始化那个内存(或“Patton”,就像我的Somerville,MA出生的岳父所说的那样)。 p>
然后当我想知道已经使用了多少堆栈时,我从顶部开始并向底部搜索第一个与我的模式不匹配的值。
答案 1 :(得分:2)
只需阅读%esp,并记住其值下降。您已经从环境中了解了默认的最大大小,以及线程的起点。
gcc拥有出色的装配支持,不像那里的一些薄片。
答案 2 :(得分:1)
您可以通过查看/proc/<pid>/smaps
来查看堆栈虚拟内存区域的状态。当您使用更多堆栈spa时,堆栈vma会自动增长。您可以通过检查%esp
与smaps
上堆栈区域的上限之间的距离来检查您实际使用的堆栈空间量(随着堆栈的增长)。如果您使用过多的堆栈空间,可能会遇到的第一个限制是ulimit
设置的限制。
但请记住,这些低级别的细节可能会有所变化,恕不另行通知。不要指望所有Linux内核版本和所有glibc版本都具有相同的行为。我永远不会让我的程序依赖这些信息。
答案 3 :(得分:0)
这很大程度上取决于您的操作系统及其内存管理。在Linux上,您可以使用procfs。它类似于/ proc / $ PID / memory。我现在不在Linux机上。
GCC通常会为寄存器添加16位(跳回到引用的函数上下文)到堆栈帧。通常,您可以通过反汇编获得有关如何精确编译程序的更多信息。或者使用-S来获得装配。
答案 4 :(得分:0)
如果您的应用程序需要确保它可以使用X MB内存,那么通常的方法是让进程在启动时分配它(如果无法分配最低要求,则无法启动)。
这当然意味着应用程序必须使用自己的内存管理逻辑。
答案 5 :(得分:0)
Tcl在某个时候进行了堆栈检查,以避免因无限制的递归或其他堆栈外问题而崩溃。不太便携,例如崩溃在其中一个BSD上......但你可以尝试找到他们使用的代码。