我是不是需要在 .NET 中显式确定堆栈的大小?

Posted

技术标签:

【中文标题】我是不是需要在 .NET 中显式确定堆栈的大小?【英文标题】:Do I need to explicitly size the stack in .NET?我是否需要在 .NET 中显式确定堆栈的大小? 【发布时间】:2016-02-16 14:21:16 【问题描述】:

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

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

    我注意到我的程序在 32 位模式但不是在 64 位模式(我感兴趣的主要模式)时经常以 *** exceptions 崩溃。

初步假设

    在 32 位模式下,您需要显式增加堆栈的大小。

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

【问题讨论】:

在 .NET 中,数组是引用类型,它们位于堆上。堆栈溢出错误是由于您的代码造成的,因此您应该发布一些。 查看answer,希望对您有所帮助 【参考方案1】:

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 位代码中。考虑替换它或对其进行分区或添加对数据集大小的检查并抢先抛出异常。

【讨论】:

我认为尾调用优化值得详细阐述,这是 x86 和 x64 JIT 行为之间的显着差异,它对抛出 ***Exception 的倾向的影响比线程堆栈大小要大得多。

以上是关于我是不是需要在 .NET 中显式确定堆栈的大小?的主要内容,如果未能解决你的问题,请参考以下文章

是否需要在C ++析构函数中显式销毁结构中固定大小的数组?

在 C++ 中显式删除移动构造函数的用例 [关闭]

私有成员是不是应该在惯用的 C# 中显式声明为私有? [关闭]

在 QT 中显式调用paintGL

id 主键是不是必须在从 inspectdb 针对现有数据库生成的 Django 模型中显式定义?

在 XML 查询中显式定义数据类型,以便 s-s-rS 从 WCF 服务中识别