获取线程堆栈基地址:作为wj32 showed,使用线程信息块的StackBase
。
获取线程堆栈大小:确定线程保留堆栈大小(它是最大大小)是不同的。 StackLimit
显示的是lowest commited address,它可以显示堆栈有多大,而不是限制。也不是您传递给CreateThread
的堆栈大小是初始提交大小,除非您通过STACK_SIZE_PARAM_IS_A_RESERVATION
标志,否则不是预留大小。程序的堆栈大小由linker parameter指定,如果不指定,则默认为1MB。所以很可能所有的线程都有1MB的堆栈保留。
由于最后一页的stack is a guard page你可以想见,从StackPage
开始,检查每一个较低的栈页面VirtualQuery
找到gaurd网页,将在堆栈的结束。这当然完全依赖于实现定义的行为。
获取当前堆栈指针:您可以使用StackLimit
,让您的堆栈的最大大小COMMITED,但是这是不一样的当前指针。 esp
显然是当前的堆栈位置,可能会高于StackLimit
。
关于保留vs提交的注意事项。在Windows中保留意味着虚拟地址已被保留供使用,并且不能用于其他目的。保留地址不消耗任何物理或虚拟内存。一旦它被提交,地址将被映射到物理或虚拟内存并且可以被使用。 Windows用户线程具有固定的堆栈保留大小 - 为堆栈保留地址空间并且不能增加和变量提交大小 - 堆栈将仅使用(提交)内存,因为它需要它。
编辑
我在检查gaurd页面将无法正常工作的想法。我编写了一个测试程序,警卫页面被设置为提交限制,所以这是行不通的。但是我确实发现,在堆栈上的任何位置运行VirtualQuery
将给出堆栈中最低地址的AllocationBase
,因为保留区大小一次分配。以下示例显示了这个动作:
#include <windows.h>
#include <WinNT.h>
#include <stdio.h>
DWORD GetThreadStackSize()
{
SYSTEM_INFO systemInfo = {0};
GetSystemInfo(&systemInfo);
NT_TIB *tib = (NT_TIB*)NtCurrentTeb();
DWORD_PTR stackBase = (DWORD_PTR)tib->StackBase;
MEMORY_BASIC_INFORMATION mbi = {0};
if (VirtualQuery((LPCVOID)(stackBase - systemInfo.dwPageSize), &mbi, sizeof(MEMORY_BASIC_INFORMATION)) != 0)
{
DWORD_PTR allocationStart = (DWORD_PTR)mbi.AllocationBase;
return stackBase - allocationStart;
}
return 0;
}
DWORD WINAPI ThreadRtn(LPVOID param)
{
DWORD stackSize = GetThreadStackSize();
printf("%d\n", stackSize);
return 0;
}
int main()
{
ThreadRtn(NULL);
HANDLE thread1 = CreateThread(NULL, 65535, ThreadRtn, NULL, 0, NULL);
WaitForSingleObject(thread1, -1);
HANDLE thread2 = CreateThread(NULL, 65535, ThreadRtn, NULL, STACK_SIZE_PARAM_IS_A_RESERVATION, NULL);
WaitForSingleObject(thread2, -1);
return 0;
}
此输出:
,它应。
请注意[Itanium有*两个堆栈*](http://blogs.msdn.com/b/oldnewthing/archive/2005/04/21/410397.aspx)。到目前为止,每个人都只关注本地变量栈,但也有寄存器栈(这是返回地址去哪里等)。所以这种技术不足以防止堆栈溢出,因为您只检查其中一个堆栈。 – 2011-12-31 15:49:39
有趣......但如果这个“寄存器堆栈”实际上是与硬件相关的,那么如果寄存器堆栈已满,那么不应该由Intel或者实现它的人使用常规调用堆栈来进行局部变量分配;毕竟,使用寄存器来存储局部变量不是必须的,不是吗? – Jong 2011-12-31 17:17:53
没有法律规定所有处理器必须与x86相同。 (Itanium几乎不是唯一带有注册窗口的处理器。) – 2011-12-31 18:14:04