你能用VirtualAlloc“分配”堆栈空间吗?

时间:2014-05-07 22:38:29

标签: winapi memory-management x86

我正在弄乱VirtualAlloc和动态代码生成,我对某些事情感到好奇。

VirtualAlloc的第一个参数指定要分配的地址范围的开始,或者更准确地说,包含该地址的页面指定页面范围的开始< / em>待分配。正确?

我开始疑惑。你可以在堆栈上创建一堆空间并用VirtualAlloc“分配”该内存吗?例如,要将其权限更改为PAGE_EXECUTE_READWRITE

(作为上述内容的扩展,我很好奇在Windows进程中堆栈的确切位置。它是如何设置的?是什么设置它?)

tl; dr 您可以使用VirtualAlloc“分配”堆栈空间吗?

1 个答案:

答案 0 :(得分:2)

在创建线程时,堆栈空间由VirtualAllocMEM_RESERVE标志(或者可能直接使用底层系统调用)分配。这会导致为该线程堆栈保留进程地址空间的chuck。

当堆栈超过实际提交的区域时,保护页面用于导致访问冲突。操作系统通过提交额外的内存(如果有足够的保留空间)或者在到达保留区域的边缘时为进程生成EXCEPTION_STACK_OVERFLOW来自动处理此问题。在第一种情况下,建立新的防护页面。在第二步中,如果您尝试处理该异常并恢复,则重新创建保护页面是一个重要步骤。

您可以使用VirtualAllocVirtualProtect预先提交线程的堆栈。但是它们没有触及堆栈指针,所以它们不能用于堆栈分配(使用堆栈指针的代码会很乐意重用“你的”自动变量,函数参数等的分配)。要从堆栈中分配空间,您需要调整堆栈指针。大多数C和C ++编译器为此提供了_alloca()内在函数。

如果您正在进行动态代码生成,请不要使用堆栈。不可执行的堆栈是对远程执行漏洞的有价值的保护。您当然可以在这样的特殊情况下使用VirtualAlloc进行动态分配,而不是通用分配器HeapAllocmalloc以及new[]。通用分配器最终都是从VirtualAlloc获取内存,但是然后将其分成不与页面边界对齐的块。