我有一个本机c ++应用程序,我从中调用.net dll(外部函数),我看到当我调用managed时,它会为使用/ stack链接器选项指定的线程分配完整的堆栈,但是如果我只进行本机函数调用,它会分配计算所需的堆栈。
以下是我的观察
当我们调用.Net外部函数时,还有一些与GC相关的额外线程。与我们不调用.Net外部函数的情况相比,我们的应用程序中的线程也使用了更多的堆栈空间。我不确定托管堆栈是否位于本机堆栈之上。有人可以帮助我理解为什么在调用.Net外部函数以及混合模式应用程序中的内存管理时分配线程的完整堆栈。
答案 0 :(得分:2)
好的,我终于找到了答案。
一旦创建托管线程,CLR总是为托管线程提交整个堆栈内存,或者当本机线程成为托管线程时,懒惰地提交。这样做是为了确保执行引擎可以预测地处理堆栈溢出。
在托管代码中,System.Threading.Thread类的构造函数提供了两个接受maxStackSize参数的重载。由于在创建时为所有托管线程提交了完整堆栈,因此maxStackSize参数同时表示保留和提交大小:它们实际上是相同的。
为了澄清,在堆栈上使用内存有三个步骤:
为进程中的堆栈保留虚拟地址空间 提交页面 使用页面
正常的Win32程序中的默认行为是在线程启动时只执行1。问题在于动态堆栈增长可能在高负载下失败 - 您可能会发现,当您想要添加堆栈帧时,系统没有可用的任何可用虚拟内存。
通过执行步骤2,CLR可确保将内存保留在备用状态,以便步骤3永远不会失败。
有关此的任何有用信息仍然受到赞赏。 谢谢。