如何为 .NET 程序更改堆栈大小?

34

我有一个程序需要递归调用20亿次,但程序出现了栈溢出的错误。我进行了修改,现在只需要40K个递归调用,所以我可能需要几兆字节的堆栈内存。我听说堆栈大小默认为1MB。我在网上搜索了一下,有人说可以通过属性->链接器……在Visual Studio中设置,但我找不到这个选项。

有人知道如何增加堆栈大小吗?此外,我想知道是否可以在我的C#程序中设置。

附言:我使用的是32位winXP和64位win7。

4个回答

47
从.NET 2.0和Win XP开始,设置堆栈大小的最简单方法是使用所需的堆栈大小生成一个新线程:
using System.Threading;

Thread T = new Thread(threadDelegate, stackSizeInBytes);
T.Start();

要更改整个程序的堆栈大小,您需要使用editbin命令:

EDITBIN.EXE /STACK:<stacksize> file.exe

4
对于那些使用editbin方法的人,您需要在Visual Studio安装程序中下载Visual C++工具集。您还可以将其放入后构建步骤中,作为“EDITBIN.EXE /STACK:<stacksize> $(TargetName)” - Cameron Aavik
1
补充一下@CameronAavik的评论,我需要将SDK工具文件夹添加到我的路径中,重新启动Visual Studio才能看到这个更改,并使用$(TargetPath)而不是$(TargetName) - Jamie Thomas
@JamieThomas 继续你的评论,你可以在 post-build 事件命令行中添加以下内容,而不是更改路径:call "$(DevEnvDir)..\tools\VsDevCmd.bat" - mbabramo
澄清我的评论:那并不总是有效。将PATH环境变量设置为包含editbin的文件夹将起作用。然后可以在.csproj文件中使用Target元素和Name="PostBuild"以及AfterTargets="PostBuildEvent"来包含Exec元素中的命令。 - mbabramo

20
没有编译器选项可以做到这一点。您可以使用editbin /stack在事后进行编辑,或者为算法创建一个单独的线程,并在Thread constructor中指定更大的堆栈大小。
话虽如此,您可能希望将递归函数扁平化...如果您现在遇到了堆栈溢出问题,很难知道任何堆栈大小在长期内都是合适的。这只是一个临时解决方案。

9

在处理问题时,很可能应该尝试使用循环而不是递归。


让我们更加精确一些:问题并不是递归本身,也不是迭代次数(毕竟,在转换为循环后仍将有20亿次迭代)。真正的问题在于编译器可能无法生成尾调用;只有因为这个原因,递归结合高数量的迭代才会成为问题。 - stakx - no longer contributing

-1

我知道在VS中你可以设置任意的堆栈大小(编辑:对于C++程序)。然而,我建议你使用尾调用(即,返回MyFunc(args);),它会自动回收堆栈空间。然后,你可以使用一些堆分配的对象来保存状态。


1
一般来说,我认为.NET编译器不会优化尾递归调用。至少C#和VB.NET不会。 - user1172763

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接