我是否需要在.NET中显式调整堆栈大小?

时间:2015-11-15 11:36:41

标签: c# .net memory stack

我使用.NET中的大arraystruct类型,远远大于为堆栈分配的标准1MB(每个线程)。我现在只关心主线程。

  1. 我读过一篇旧文章(可能已过时),提到明确调整堆栈大小:http://content.atalasoft.com/h/i/58213648-increasing-the-size-of-your-stack-net-memory-management-part-3

  2. 我注意到我的程序在32位模式下经常与stackoverflow exceptions崩溃,但不是64位模式(我感兴趣的主要模式)。

  3. 暂定假设

    1. 当你处于32位模式时,你需要明确增加堆栈的大小。

    2. .NET框架在64位模式下隐式调整堆栈大小(即使此行为与64位模式不一致)。

1 个答案:

答案 0 :(得分:4)

C#和VB.NET编译器没有办法指定主线程的初始堆栈大小。 C ++ / CLI编译器可以。在post-build event中使用Editbin.exe是一种简单的解决方法。

此选项未公开,因为托管代码的默认堆栈大小非常慷慨。与C和C ++等非托管语言不同,没有简单的方法可以使用声明来消耗大量的堆栈。数组和字符串是引用类型,因此在GC堆上分配,而不是堆栈。

打击堆栈的唯一好方法是使用不安全的stackalloc关键字,一个你从不使用的关键字。或者通过递归,无论是偶然的(迄今为止最常见的情况)还是使用比O(logN)更差的递归算法。这些问题严重倾向于 bug ,Editbin.exe只是一个创可贴,因为当数据集足够大时你仍然会摧毁堆栈。

唯一值得注意的其他细节是,如果你专门目标x64,初始堆栈大小将是4MB而不是1MB。一般来说也是一个错误,你总是喜欢AnyCPU。

所以盲目的建议就是开始寻找那个递归代码。它不应该远离生成SOE的语句,至少在堆栈跟踪中可见。注意O(N)尾草草,你不能指望它得到优化,绝对不是32位代码。考虑替换它或对其进行分区或对数据集大小添加检查并先发制人地抛出异常。