我的Win32 C++应用程序充当RPC服务器 - 它有一组用于处理请求的函数,RPC运行时创建一个单独的线程并调用该线程中的一个函数.
在我的函数中,我有一个std :: auto_ptr,它用于控制在编译时已知的堆分配的char []数组.它在使用VC++编译时非常有效,但根据C++标准,它是未定义的行为,我想摆脱它.
我有两个选项:std :: vector或堆栈分配的数组.由于我不知道为什么有堆分配的数组,我想考虑用堆栈分配的数组替换它.该数组是10k元素,如果RPC运行时生成一个堆栈非常小的线程,我可以假设它面临堆栈溢出.
我想检测一下典型地为线程分配了多少堆栈空间,以及我的函数有多少可用(它的被调用者肯定会消耗一些分配的空间).我怎么能这样做?
如果您无法访问该CreateThread
调用,或者如果它是主线程,则查看EXE在PE头中的默认线程大小,我不知道如何使用API直接计算堆栈大小.
在你的情况下,我会在堆上分配是安全的,即使10K数组的小数据不可能在非递归场景中最大化堆栈.
但是,如果仔细进行,您可以探测堆栈限制.当您触摸它们时(通过保护页面),堆栈将以4K页面提交,直到达到限制为止,Windows将引发堆栈溢出异常.调度异常时仍然有一页堆栈,因此异常调度逻辑本身(包括过滤器函数)可以执行 - 但Windows抛出异常,因为它无法分配另一个防护页面.这意味着下一个堆栈溢出或探测不会导致堆栈溢出异常,但会导致访问冲突.因此,为了使探测工作可靠(特别是可重复),您需要解除探测分配的内存并恢复保护页面.
关于KB的这篇文章介绍了如何解除堆栈内存并恢复保护页面.它使用递归和10,000字节增量进行探测; 默认情况下,编译器实现自己的堆栈探测,查找本地> 4KB的堆栈分配,以便堆栈增长机制正常工作.