使用 Visual Studio 确定堆栈空间 [英] Determining Stack Space with Visual Studio
问题描述
我在 Visual Studio 2005 中使用 C 进行编程.我有一个多线程程序,但这在这里并不是特别重要.
我如何确定(大约)我的线程使用了多少堆栈空间?
我计划使用的技术是将堆栈内存设置为某个预定值,比如 0xDEADBEEF,长时间运行程序,暂停程序,并调查堆栈.
如何使用 Visual Studio 读写堆栈内存?
参见,例如,如何确定最大堆栈使用量." 这个问题是关于嵌入式系统的,但在这里我试图在普通 PC 上确定答案.
Windows 不会立即提交堆栈内存;相反,它为其保留地址空间,并在访问时逐页提交.阅读此页面了解更多信息.>
因此,堆栈地址空间由三个连续区域组成:
- 保留但未提交的内存,可用于堆栈增长(但尚未访问);
- 保护页面,它也从未被访问过,并且在访问时触发堆栈增长;
- 提交的内存,即线程曾经访问过的堆栈内存.
这允许我们构造一个获取堆栈大小(具有页面大小粒度)的函数:
static size_t GetStackUsage(){MEMORY_BASIC_INFORMATION mbi;VirtualQuery(&mbi, &mbi, sizeof(mbi));//现在 mbi.AllocationBase = 保留的堆栈内存基地址VirtualQuery(mbi.AllocationBase, &mbi, sizeof(mbi));//现在 (mbi.BaseAddress, mbi.RegionSize) 描述堆栈的保留(未提交)部分//跳过它VirtualQuery((char*)mbi.BaseAddress + mbi.RegionSize, &mbi, sizeof(mbi));//现在 (mbi.BaseAddress, mbi.RegionSize) 描述保护页//跳过它VirtualQuery((char*)mbi.BaseAddress + mbi.RegionSize, &mbi, sizeof(mbi));//现在 (mbi.BaseAddress, mbi.RegionSize) 描述堆栈的已提交(即访问)部分返回 mbi.RegionSize;}
需要考虑的一件事:CreateThread
允许指定初始堆栈提交大小(通过 dwStackSize
参数,当 STACK_SIZE_PARAM_IS_A_RESERVATION
标志未设置时).如果此参数不为零,则只有当堆栈使用量大于 dwStackSize
值时,我们的函数才会返回正确的值.
I'm programming in C in Visual Studio 2005. I have a multi-threaded program, but that's not especially important here.
How can I determine (approximately) how much stack space my threads use?
The technique I was planning to use is setting the stack memory to some predetermined value, say 0xDEADBEEF, running the program for a long time, pausing the program, and investigating the stack.
How do I read and write stack memory with Visual Studio?
EDIT: See, for example, "How to determine maximum stack usage." That question talks about an embedded system, but here I'm trying to determine the answer on a regular PC.
Windows does not commit the stack memory immediately; instead, it reserves the address space for it, and commits it page-by-page when it is accessed. Read this page for more info.
As a result, stack address space consists of three contiguous regions:
- Reserved but uncommitted memory which can be used for stack growth (but was never accessed yet);
- Guard page, which was never accessed yet too, and serves to trigger stack growth when accessed;
- Committed memory, i.e. stack memory which was ever accessed by the thread.
This allows us to construct a function that obtains stack size (with page size granularity):
static size_t GetStackUsage()
{
MEMORY_BASIC_INFORMATION mbi;
VirtualQuery(&mbi, &mbi, sizeof(mbi));
// now mbi.AllocationBase = reserved stack memory base address
VirtualQuery(mbi.AllocationBase, &mbi, sizeof(mbi));
// now (mbi.BaseAddress, mbi.RegionSize) describe reserved (uncommitted) portion of the stack
// skip it
VirtualQuery((char*)mbi.BaseAddress + mbi.RegionSize, &mbi, sizeof(mbi));
// now (mbi.BaseAddress, mbi.RegionSize) describe the guard page
// skip it
VirtualQuery((char*)mbi.BaseAddress + mbi.RegionSize, &mbi, sizeof(mbi));
// now (mbi.BaseAddress, mbi.RegionSize) describe the committed (i.e. accessed) portion of the stack
return mbi.RegionSize;
}
One thing to consider: CreateThread
allows to specify initial stack commit size (via dwStackSize
parameter, when STACK_SIZE_PARAM_IS_A_RESERVATION
flag is not set). If this parameter is nonzero, our function will return correct value only when stack usage becomes greater than dwStackSize
value.
这篇关于使用 Visual Studio 确定堆栈空间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!