估计线程堆栈大小

时间:2011-11-10 05:02:51

标签: c stack-overflow

我试图猜测每个线程分配多少堆栈。 找到暗示程序应该在内存中写入已知模式(例如:0xEF)的提示,以获得堆栈的上限/下限。

有人可以提供快速的C程序吗?这真的是要走的路吗? 还有其他建议吗?

感谢您协助解决这个疑问。

2 个答案:

答案 0 :(得分:1)

如果您完全控制了您的程序(代码),那么尝试查找大小是无意义的,因为会告诉操作系统在您分配特定的堆栈大小时正在使用CreateThreadpthread_create创建一个主题。但是,如果不这样做,根据您的操作系统,您可以调用pthread_attr_getstack(在unix上)或VirtualQuery(在Windows上),分配基于堆栈的变量,并计算之间的距离。堆栈的基址和变量的位置。

答案 1 :(得分:0)

估计堆栈使用情况的另一种方法是读取每个函数中的堆栈指针值并更新最小和最大堆栈指针变量。在程序结束时,两个值之间的差异将为您提供估计值。

为了读取堆栈指针的值,您可以:

  • 实现汇编函数(为x86 CPU执行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

相关问题