有什么方法可以确定运行时可用的堆栈空间吗?
我知道堆栈大小是固定的。所以我们不能在堆栈上存储大对象,我们转向动态分配(例如malloc)。此外,当存在函数调用嵌套时,会使用堆栈,因此我们也因此避免使用递归函数。有没有办法在运行时确定到目前为止使用了多少堆栈内存以及剩余多少?
这里,我假设x86架构的linux环境(gcc编译器)。
I know that stack size is fixed. So we can not store large objects on stack and we shift to dynamic allocations (e.g. malloc). Also, stack gets used when there is nesting of function calls so we avoid recursive functions as well for this reason. Is there any way at runtime to determine how much stack memory is used so far and how much is left ?
Here, I am assuming linux environment (gcc compiler) with x86 architecture.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
有一个 pthread API 可以确定堆栈所在的位置:
在 i386 上,堆栈从底部开始并向顶部增长。
所以你知道你有 ($ESP - StackAddress) 字节可用。
在我的系统中,我有一个围绕 pthread_create() 的包装器,因此每个线程都在我的私有函数中启动。在该函数中,我如上所述找到堆栈,然后找到未使用的部分,然后使用独特的模式(或“Patton”,正如我出生于马萨诸塞州萨默维尔的岳父所说的那样)初始化该内存。
然后,当我想知道堆栈已使用了多少时,我从顶部开始,向底部搜索第一个与我的模式不匹配的值。
There is a pthread API to determine where the stack lies:
On i386, the stack starts at the bottom and grows towards the top.
So you know you have ($ESP - StackAddress) bytes available.
In my system, I have a wrapper around pthread_create(), so each thread starts in my private function. In that function, I find the stack as described above, then find the unused portion, then initialize that memory with a distinctive pattern (or "Patton", as my Somerville, MA-born father-in-law would say).
Then when I want to know how much of the stack has been used, I start at the top and search towards the bottom for the first value that doesn't match my pattern.
只需读取 %esp,并记住它的值会下降。您已经从环境中知道默认的最大大小,以及线程的起点。
gcc 具有出色的汇编支持,与其他一些薄片不同。
Just read %esp, and remember its value goes down. You already know your defaulted max size from the environment, as well as your threads' starting point.
gcc has great assembly support, unlike some flakes out there.
如果您的应用程序需要确保它可以使用 X MB 内存,通常的方法是让进程在启动时分配它(如果无法分配最低要求,则无法启动)。
当然,这意味着应用程序必须采用自己的内存管理逻辑。
If your application needs to be sure it can use X MB of memory the usual approach is for the process to alloc it at startup time (and fail to start if it cannot alloc the minimum requirement).
This of course, means the application has to employ its own memory management logic.
您可以通过查看
/proc//smaps
来查看堆栈虚拟内存区域的状态。当您使用更多堆栈 Spa 时,堆栈 vma 会自动减小。您可以通过检查%esp
与smaps
上堆栈区域上限的距离(随着堆栈向下增长)来检查实际使用了多少堆栈空间。如果您使用太多堆栈空间,您将遇到的第一个限制可能是由ulimit
设置的限制。但请记住,这些低级细节可能会发生变化,恕不另行通知。不要期望所有 Linux 内核版本和所有 glibc 版本都具有相同的行为。我永远不会让我的程序依赖于这些信息。
You can see the state of the stack virtual memory area by looking at
/proc/<pid>/smaps
. The stack vma grows down automatically when you use more stack spa. You can check how much stack space you are really using by checking how far%esp
is from the upper limit of the stack area onsmaps
(as the stack grows down). Probably the first limit you will hit if you use too much stack space will be the one set byulimit
.But always remember that these low level details may vary without any notice. Don't expect all Linux kernel versions and all glibc versions to have the same behavior. I would never make my program rely on this information.
这在很大程度上取决于您的操作系统及其内存管理。在 Linux 上,您可以使用 procfs。它类似于/proc/$PID/内存。我现在不在 Linux 机器上。
GCC 通常会向堆栈帧添加 16 位寄存器(以跳回引用的函数上下文)。通常,您可以通过反汇编程序来获得有关程序到底是如何编译的更多信息。或者使用 -S 来获取程序集。
That's very much depending on your OS and its memory management. On Linux you can use procfs. It's something like /proc/$PID/memory. I'm not on a Linux box right now.
GCC generally adds 16 bits for the registers (to jump back to the function context referred from) to the stack-frame. Normally you can gain more information on how the program exactly is compiled by disassembling it. Or use -S to get the assembly.
Tcl 有时会进行堆栈检查,以避免由于无限递归或其他堆栈外问题而崩溃。不太可移植,例如在 BSD 之一上崩溃......,但您可以尝试找到他们使用的代码。
Tcl had a stack check at some time, to avoid crashing due to unlimted recursion or other out of stack issues. Wasn't too portable, e.g. crashed on one of the BSDs..., but you could try to find the code they used.