2011-03-18 51 views
4

我正在做一个叫做“堆画”的技巧。确定一个特定函数使用多少堆栈空间。Windows会回收堆栈空间吗?

如果我分配了堆栈上1MB的物品。然后确定我没有使用任何这些物品。是否Windows 自动取消(免费)这些未使用的页面?

我想知道具体关于Windows的VMM。关于页面是否提交或不一定comices,但只是保留

换句话说,如果我手动访问内存下降到1MB可能窗口会引发访问冲突?

+1

以及你*可能会得到一个堆栈溢出,所以它很好你来到stackoverflow.com :) – 2011-03-18 23:22:57

+1

或者,你可以尝试BufferOverflow.com。 ;)嗯......也许StackOverflow应该保留该域名? – 2011-03-18 23:28:52

回答

3

要回答你的第一个问题,没有Windows不会解除这些页面。任何作为堆栈提交的页面都会一直保持,直到线程终止。

要回答第二个问题,相关字段位于IMAGE_OPTIONAL_HEADER32或IMAGE_OPTIONAL_HEADER64结构中。他们是SizeOfStackReserve和SizeOfStackCommit。这个结构是PE的NT头部分的一部分,而后者又从MSDOS头部引用(在PE中以偏移量0开始并且具有“MZ”作为魔术值的东西)。

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

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

+0

如果有人对编译器如何使用保护页方案“分配”多于一页堆栈空间的情况感到好奇,它会使用类似_chkstk的东西,它会按照降序从当前的堆栈指针,以确保访问保护页并且操作系统提交页面。 – 2011-03-19 00:47:58

6

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

原则上讲,当应用程序加载到内存中时,所有的堆栈都会被分配,所以它是一个固定大小的结构,一次又一次地被重复使用(而代码流进入和退出范围)。操作系统可能会发挥聪明的技巧(通过使用保护页来提交堆栈的上半部分,这只是在应用程序的开始时保留的),但通常这不应该涉及到你。

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


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

编辑

。换句话说,如果我手动访问存储下来到1MB可以窗户抛出一个访问冲突?

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

Windows并不知道该堆栈的那部分不再被使用。 Windows可以检测是否必须提交更多页面,使用保护页检测对堆栈上部的访问,但不知道这些页面不再使用。实际上,它可以在上下文切换时查找堆栈指针,但是它会打破应用程序,使堆栈中的事情变得“聪明”,总的来说,这将是一项不值得花费的优化:如果不存在记忆这些页面仍然可以被分页。

尽管如此,为了安全起见(例如,如果你不知道这个分配是否已经发生),你应该从当前使用的部分向上读取堆栈,所以如果页面向上没有被提交,你仍然会触摸警戒页面,提醒Windows提交更多页面的堆栈。

+0

这也是一个很好的答案。 – unixman83 2011-03-18 23:40:46

+0

@ unixman83:谢谢! ':)' – 2011-03-18 23:42:01