Windows是否会回收堆栈空间?

时间:2011-03-18 23:20:51

标签: c windows stack

我正在做一种叫做“叠画”的技巧。确定特定函数使用了多少堆栈空间。

如果我在堆栈上分配了 1MB的物品。然后我确定我没有使用任何这些项目。 Windows 会自动解除(免费)这些未使用的页面吗?

我特别想知道Windows的VMM。关于页面是否已提交或未必提交但仅保留

换句话说,如果我手动访问内存到1MB,那么windows会引发访问冲突吗?

2 个答案:

答案 0 :(得分:6)

你不删除在堆栈上分配的东西;它会自动回收,因为当您从当前作用域退出时,堆栈指针会移回到前一个堆栈帧 1 ,因此有效回收当前作用域中对象所用的所有内存。 / p>

原则上,当应用程序加载到内存中时,所有堆栈都被分配,因此它是一个固定大小的结构,可以反复重复使用(当代码流进出范围时);操作系统可能会发挥巧妙的技巧(通过使用保护页面提交堆栈的上半部分,这只是在应用程序启动时保留),但一般来说这不应该与你有关。

堆栈大小是PE头(可执行文件的头)的一部分,您可以使用链接器选项进行设置。您可以通过窥探在内存中加载的PE结构来检索已加载的可执行文件的此类值(基本上它的HMODULE是可执行文件在内存中映射的位置);我认为ImageHelper库在此任务中非常有用。


  1. 自然地,在析构函数运行之后;顺便说一句,FPO可以在这里稍微改变一下,但概念保持不变。

  2. 修改

      

    换句话说,如果我手动访问内存到1MB,那么windows会引发访问冲突吗?

    如果它已经被提交(即你在堆栈上分配和释放了1 MB的对象),我认为它不会发生。

    Windows不会知道堆栈的那部分已不再使用。 Windows可以检测是否必须提交更多页面,使用保护页面来检测对堆栈上半部分的访问,但它无法知道这些页面不再使用。

    实际上它可以在上下文切换时查找堆栈指针,但它会破坏使用堆栈做“聪明”事情的应用程序,并且通常这将是一个不值得努力的优化:如果没有内存这些页面仍然可以被分页。

    尽管如此,为了安全起见(例如,如果您不知道该分配是否已经发生),您应该从当前使用的部分向上阅读堆栈,因此如果页面向上还没有提交,那么你会仍然触摸防护页面,提醒Windows为堆栈提交更多页面。

答案 1 :(得分:3)

要回答您的第一个问题,Windows不会拒绝这些页面。在线程终止之前,任何以堆栈形式提交的页面都会保持不变。

要回答第二个问题,相关字段位于IMAGE_OPTIONAL_HEADER32或IMAGE_OPTIONAL_HEADER64结构中。它们是SizeOfStackReserve和SizeOfStackCommit。这个结构是PE的NT头的一部分,它反过来是从MSDOS头引用的(在PE中以偏移量0开始,“MZ”作为魔术值)。

Microsoft的link.exe具有“/ STACK:reserve [,commit]”开关,它直接与这两个字段相关。

自问题发生变化后进行编辑:您只能可靠地访问堆栈的已提交页面和当前防护页面。如果您访问不是保护页面的保留页面,您应该期望AV(如果您访问最后一个保护页面,您将获得SEH堆栈溢出异常)。