我在 Visual Studio 2005 中使用 C 语言进行编程。我有一个多线程程序,但这在这里并不是特别重要。
如何确定(大约)我的线程使用了多少堆栈空间?
我计划使用的技术是将堆栈内存设置为某个预定值,例如 0xDEADBEEF,运行程序很长时间,暂停程序并调查堆栈。
如何使用 Visual Studio 读写堆栈内存?
编辑:例如,参见 "How to determine maximum stack usage."这个问题是关于嵌入式系统的,但在这里我试图在普通 PC 上确定答案。
最佳答案
Windows 不会立即提交堆栈内存;相反,它为其保留地址空间,并在访问时逐页提交。阅读 this page了解更多信息。
因此,堆栈地址空间由三个连续的区域组成:
- 保留但未提交的内存,可用于堆栈增长(但从未访问过);
- 保护页面,也从未被访问过,在访问时触发堆栈增长;
- 已提交的内存,即线程曾经访问过的堆栈内存。
这允许我们构造一个获取堆栈大小(以页面大小为粒度)的函数:
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;
}
需要考虑的一点:CreateThread
允许指定初始堆栈提交大小(通过 dwStackSize
参数,当 STACK_SIZE_PARAM_IS_A_RESERVATION
标志未设置时)。如果此参数不为零,则只有当堆栈使用量大于 dwStackSize
值时,我们的函数才会返回正确的值。
关于c - 使用 Visual Studio 确定堆栈空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1740888/