我试图猜测每个线程分配多少堆栈。
找到暗示程序应该在内存中写入已知模式(例如:0xEF
)的提示,以获得堆栈的上限/下限。
有人可以提供快速的C程序吗?这真的是要走的路吗? 还有其他建议吗?
感谢您协助解决这个疑问。
答案 0 :(得分:1)
如果您完全控制了您的程序(代码),那么尝试查找大小是无意义的,因为您会告诉操作系统在您分配特定的堆栈大小时正在使用CreateThread
或pthread_create
创建一个主题。但是,如果不这样做,根据您的操作系统,您可以调用pthread_attr_getstack
(在unix上)或VirtualQuery
(在Windows上),分配基于堆栈的变量,并计算之间的距离。堆栈的基址和变量的位置。
答案 1 :(得分:0)
估计堆栈使用情况的另一种方法是读取每个函数中的堆栈指针值并更新最小和最大堆栈指针变量。在程序结束时,两个值之间的差异将为您提供估计值。
为了读取堆栈指针的值,您可以:
mov r/eax, r/esp
+ ret
)代码:
#include <stdint.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
// uintptr_t is an unsigned integer type from stdint.h
// that is capable of holding a pointer.
// If you don't have it in your compiler, use an
// equivalent, which may be size_t (stddef.h) or
// UINT_PTR (windows.h) or something else.
uintptr_t StackPointerMin = (uintptr_t)-1;
uintptr_t StackPointerMax = 0;
void UpdateStackUsageInner(int dummy, ...)
{
va_list ap;
volatile char* p;
uintptr_t StackPointer;
va_start(ap, dummy);
p = va_arg(ap, volatile char*);
StackPointer = (uintptr_t)p;
if (StackPointer < StackPointerMin) StackPointerMin = StackPointer;
if (StackPointer > StackPointerMax) StackPointerMax = StackPointer;
va_end(ap);
}
void UpdateStackUsage()
{
volatile char c = 'a';
UpdateStackUsageInner(0, &c);
}
void DoSomething(void)
{
char c[1024+1];
UpdateStackUsage();
memset(c, '*', sizeof(c));
c[sizeof(c)-1] = '\0';
printf("%s\n", c);
}
int main(void)
{
UpdateStackUsage();
DoSomething();
printf("Approximate stack usage: %lu\n",
(unsigned long)(StackPointerMax - StackPointerMin));
return 0;
}
输出:
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
********************************************************************************
****************************************************************
Approximate stack usage: 1040
我也知道有些编译器支持挂钩函数入口(可能退出),这可以简化任务,因为这样你就不需要在所有/多个函数中插入UpdateStackUsage();
。已经讨论过here。