为什么 C# 中的堆栈大小正好是 1 MB?

2023-12-19

如今的 PC 拥有大量物理 RAM,但 C# 的堆栈大小对于 32 位进程仅为 1 MB,对于 64 位进程仅为 4 MB(C# 中的堆栈容量 https://stackoverflow.com/questions/823724/stack-capacity-in-c-sharp).

为什么 CLR 中的堆栈大小仍然如此有限?

为什么它正好是 1 MB (4 MB)(而不是 2 MB 或 512 KB)?为什么决定使用这些金额?

我对感兴趣该决定背后的考虑因素和理由.


你正在看着那个做出这个选择的人。 David Cutler 和他的团队选择 1 MB 作为默认堆栈大小。与 .NET 或 C# 无关,这在他们创建 Windows NT 时就已经确定了。当程序的 EXE 标头或 CreateThread() winapi 调用未明确指定堆栈大小时,它会选择 1 MB。这是正常的方式,几乎所有程序员都会让操作系统来选择大小。

这个选择可能早于 Windows NT 设计,历史对此太模糊了。如果卡特勒能写一本关于这方面的书就好了,但他从来都不是作家。他对计算机的工作方式具有非凡的影响力。他的第一个操作系统设计是 RSX-11M,这是一个用于 DEC 计算机(数字设备公司)的 16 位操作系统。它严重影响了 Gary Kildall 的 CP/M,这是第一个像样的 8 位微处理器操作系统。这极大地影响了 MS-DOS。

他的下一个设计是 VMS,这是一个支持虚拟内存的 32 位处理器操作系统。非常成功。他的下一个项目在 DEC 开始解体时被取消,因为无法与廉价的 PC 硬件竞争。提示微软,他们向他提出了一个他无法拒绝的提议。他的许多同事也加入了。他们开发了 VMS v2,也就是众所周知的 Windows NT。 DEC对此感到不满,并通过金钱转手来解决此事。我不知道VMS是否已经选择了1兆字节,我只了解RSX-11。这并非不可能。

足够的历史了。一兆字节是一个lot,一个真正的线程很少消耗超过几千字节的资源。所以一兆字节实际上是相当浪费的。然而,在按需分页虚拟内存操作系统上,这是您可以承受的浪费,兆字节只是虚拟内存。只是处理器的编号,每 4096 字节一个。在实际寻址之前,您永远不会真正使用物理内存(机器中的 RAM)。

它在 .NET 程序中显得格外过多,因为最初选择 1 MB 大小是为了容纳本机程序。这往往会创建大型堆栈帧,并在堆栈上存储字符串和缓冲区(数组)。缓冲区溢出因作为恶意软件攻击媒介而臭名昭著,可以用数据操纵程序。 .NET 程序的工作方式不同,字符串和数组在 GC 堆上分配并检查索引。使用 C# 在堆栈上分配空间的唯一方法是使用不安全的堆栈分配关键词。

.NET 中堆栈的唯一重要用途是抖动。它使用线程堆栈将 MSIL 即时编译为机器代码。我从未见过或检查过它需要多少空间,这取决于代码的性质以及是否启用优化器,但粗略猜测几十千字节。这就是这个网站得名的原因,.NET 程序中的堆栈溢出是相当致命的。没有足够的空间(少于 3 KB)来仍然可靠地 JIT 尝试捕获异常的任何代码。 Kaboom 到桌面是唯一的选择。

最后但并非最不重要的一点是,.NET 程序对堆栈执行的操作效率很低。 CLR 将commit线程的堆栈。这是一个昂贵的词,意味着它不仅保留堆栈的大小,还确保在操作系统的分页文件中保留空间,以便在必要时始终可以交换堆栈。未能提交是致命错误并无条件终止程序。这种情况只发生在内存很少、运行太多进程的机器上,这样的机器在程序开始死亡之前就会变成糖蜜。 15 多年前可能存在的问题,而不是今天。程序员将他们的程序调整为像 F1 赛车一样使用<disableCommitThreadStack> https://msdn.microsoft.com/en-us/library/bb882564%28v=vs.110%29.aspx.config 文件中的元素。

Fwiw,卡特勒并没有停止设计操作系统。这张照片是他在 Azure 工作时拍摄的。


更新,我注意到.NET 不再提交堆栈。不完全确定何时或为何发生这种情况,距离我检查已经太久了。我猜测这个设计更改发生在 .NET 4.5 左右。相当明智的改变。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 C# 中的堆栈大小正好是 1 MB? 的相关文章

  • Unity3D StartCoroutine 调用一个函数,该函数什么时候返回?

    我知道Unity3D StartCoroutine调用了一个与StartCoroutine在同一线程上运行的函数 但是被调用的函数什么时候返回到原始调用者 我在互联网上查找了一个很好的 Unity3D Coroutine 示例 但找不到完整
  • 以相反的顺序迭代可变参数模板参数

    如果我手动反转传递给它的模板参数的顺序 以下代码将起作用 template
  • C修改printf()输出到文件

    有没有办法修改printf为了将字符串输出到文件而不是控制台 我尝试在互联网上查找一些内容 发现了类似的电话dup dup2 and fflush这可能与此有关 EDIT 也许我不清楚 问题是这是C考试问题 问题如下 解释一个通常将字符串输
  • 切换图片框可见性 C#

    为什么图片框控件的可见性属性在这里不起作用 我最初将它们设置为 false 以便在屏幕加载时它们不可见 但后来我想切换这个 我已完成以下操作 但似乎不起作用 这是一个 Windows 窗体应用程序 private void Action w
  • C# 中的协变和逆变

    首先我要说的是 我是一名正在学习 C 编程的 Java 开发人员 因此 我会将我所知道的与我正在学习的进行比较 我已经使用 C 泛型几个小时了 我已经能够在 C 中重现我在 Java 中知道的相同内容 除了几个使用协变和逆变的示例 我正在读
  • 如何使用汇编获取BIOS时间?

    我正在从头开始实现一个小型操作系统 用于教育目的 现在 我想使用汇编来获取 BIOS 时间 我对此进行了很多搜索 但找不到任何代码示例来执行此操作 如果有人可以提供任何参考或代码示例或与此相关的任何内容 我将非常感激 See 时钟中断 1a
  • rand() 播种与 time() 问题

    我很难弄清楚如何使用 rand 并使用 Xcode 用 time 为其播种 我想生成 0 到 1 之间的随机十进制数 该代码为我提供了元素 1 和 2 看似随机的数字 但元素 0 始终在 0 077 左右 有什么想法吗 我的代码是 incl
  • 将 C# 反射代码移植到 Metro-Ui

    我正在尝试移植使用反射的现有 C 类 通用工厂 但我无法编译这段代码 Type types Assembly GetAssembly typeof TProduct GetTypes foreach Type type in types i
  • C 中的模仿函数重写

    具体来说 函数重写能够调用基本重写方法 这有两部分 一个是预编译的库代码 1 另一个是库的用户代码 2 我在这里实现了一个尽可能最小的经典 Person 和 Employee 示例 非常感谢了解 OOP 概念的铁杆 C 开发人员的回应 我正
  • 使用反射获取基类的受保护属性值

    I would like to know if it is possible to access the value of the ConfigurationId property which is located in the base
  • 使用scanf()时如何区分整数和字符

    我只是使用该功能scanf 代码如下 scanf d a printf d a 当我输入1时 它会像我想要的那样打印1 但即使我输入 1a 它也会像以前一样打印 1 当用户输入非整数时 例如 2 3 12ab 1 a 我想向用户显示 输入整
  • 不要声明只读可变引用类型 - 为什么不呢?

    我一直在阅读这个问题 https stackoverflow com questions 2274412 immutable readonly reference types fxcop violation do not declare r
  • 如何在 C# 中使用 XmlDsigC14NTransform 类

    我正在尝试使用规范化 xml 节点System Security Cryptography Xml XMLDsigC14nTransformC net Framework 2 0 的类 该实例需要三种不同的输入类型 NodeList Str
  • 为什么WCF中不允许方法重载?

    假设这是一个ServiceContract ServiceContract public interface MyService OperationContract int Sum int x int y OperationContract
  • 如何将字符串转换为 Indian Money 格式?

    我正在尝试将字符串转换为印度货币格式 例如如果输入为 1234567 则输出应为 12 34 567 我编写了以下代码 但它没有给出预期的输出 CultureInfo hindi new CultureInfo hi IN string t
  • 当在 Repository/UnitOrWork 之上使用 Service 类时,我应该在哪里放置逻辑不适合 Repository 的常用数据访问代码?

    In my 先前的问题 https stackoverflow com questions 24906548 using the generic repository unit of work pattern in large projec
  • 无法通过 LINQ to Entities 使用某些功能?

    我正在尝试使用 LINQ 查询在项目上实现搜索功能 由于数据有时包含带有重音符号和其他符号的字符 因此我创建了一种方法来删除这些字符以进行搜索 这是我的代码 var addresses from a in db Addresses join
  • 为什么C语言中可以使用多个分号?

    在 C 中我可以执行以下操作 int main printf HELLO WORLD 它有效 这是为什么 我个人的想法 分号是一个 NO OPERATION 来自维基百科 指示符 拥有一大串分号与拥有一个分号并告诉 C 语句已结束具有相同的
  • 正在获取“未终止 [] 设置”。 C# 中的错误

    我正在 C 中使用以下正则表达式 Regex find new Regex url
  • 通过 cmake 链接作为外部项目包含的 opencv 库[重复]

    这个问题在这里已经有答案了 我对 cmake 比较陌生 经过几天的努力无法弄清楚以下事情 我有一个依赖于 opencv 的项目 它本身就是一个 cmake 项目 我想静态链接 opencv 库 我正在做的是我的项目中有一份 opencv 源

随机推荐

  • Python doctest 是否消除了单元测试的需要?

    我所在项目的一位开发人员同事认为文档测试与单元测试一样好 并且如果一段代码经过文档测试 则不需要进行单元测试 我不相信情况是这样 任何人都可以提供一些可靠的 理想引用的例子来支持或反对文档测试取代单元测试需求的论点吗 谢谢 丹尼尔 编辑 任
  • 如何在 C# windows 窗体中在可缩放图像上绘图

    所以我正在实现一个可以读取图像的项目 平移它 缩放它并做其他事情 一切都很顺利 直到我尝试用鼠标右键实现绘图 问题是当我画一条线时 图像上出现的线与我在屏幕上画的线不对应 这意味着它发生了移动 并且我知道它是因为图像的大小和缩放而改变的 但
  • WhatsApp 图像共享 iOS [关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我正在开发一个 iOS 应用程序 我必须在其中从我的应用程序在 WhatsApp 上共享图像 我找到了这段代码 但它只处理文本共享https
  • 如何使用 MobileDevice 框架将文件写入我的应用程序的 Documents 目录?

    因此 我需要以编程方式将文件写入 iPhone 上的应用程序文档目录 由于许可证限制 我无法使用 libimobiledevice iphonedisk 不再维护 据我所知 无论如何您实际上都无法访问应用程序数据 所以我想我需要直接使用Mo
  • 使用 GridLayout 时可以将组件添加到特定网格单元吗?

    当我将 GridLayout 设置为 JPanel 然后添加一些内容时 它会按 文本顺序 从左到右 从上到下 顺序添加 但我想将一个元素添加到特定单元格 在第 j 列的第 i 行中 是否可以 不可以 您不能在特定单元格添加组件 您可以做的是
  • 如何从闭包表中以 HTML 形式显示树结构

    我在 MySQL 中存储一些分层数据 由于各种原因 我决定使用闭包表 而不是嵌套集 邻接表等 到目前为止 它对我来说效果很好 但现在我正在尝试弄清楚如何在 HTML 中实际显示这棵树 即使用正确的缩进 举个例子 假设我有一棵像这样的树 Fo
  • UnobservedTaskException - 任务从哪里来

    在我的 MVC 应用程序中 我有时会遇到如下异常 System Net WebException The request was aborted The request was canceled at System Net HttpWebR
  • 在主干中获取 /collection/id 而不加载整个集合

    有没有办法加载 Backbone 集合的单个实体 从服务器 Backbone Collection extend url rest product 下面的代码可以加载整个集合collection fetch 但如何加载单个模型呢 Backb
  • 当前线程方法java

    所以我正在尝试为我正在制作的游戏使用线程 我是very刚接触这个主题 所以我可能理解不正确 我的问题是 currentThread 方法在 java API 的 Thread 类中如何工作 API 说 返回对当前正在执行的线程对象的引用 但
  • T-SQL 算术溢出:哪一列?

    在MS SQL Server 2005中 当在INSERT期间遇到 将数字转换为数字类型的算术溢出错误 时 是否可以发现哪一列的输入值导致了错误 似乎有许多类似的转换错误 但没有报告哪一列引发了问题 这使得在大型查询中修复错误变得相当困难
  • IMPORTDATA 出现很多错误,因为我正在尝试加载许多单元格以获取股票报价

    我有一张包含 220 个 导入数据 功能的 Google 表格 其中每个功能都从网站上提取股票报价 功能很简单 importdata http
  • 在设置大量计时器或使用计划任务队列之间寻找解决方案

    我正在构建一项服务 游戏 其中一组用户将在一个房间中 它将在一定的持续时间 例如 30 秒 内通过每个用户做出选择 如果用户在该持续时间内没有做出选择 服务将自动为该用户生成一个选择 如果在持续时间结束之前做出选择 那么下一个用户就起来了
  • 如何阅读 VS Code 中的发行说明

    我今天重新启动了 VS Code 它已更新 当它再次打开时 我看到一个带有发行说明的选项卡 几分钟后决定打开我的项目以查看操作中的更改 然而 当我打开该项目时 发行说明选项卡已关闭 现在我找不到在 VS Code 中专门访问它的方法 有没有
  • 如何在delphi中一次将不同字体格式的文本绘制到画布上?

    我一直在使用DrawText满足我所有的 矩形文本 输出需求 但是我没有找到一种绘制字符串的方法 例如 将每个其他单词加粗或使用不同的颜色 或者更糟糕的是 为所述随机选择的单词使用不同的背景 据我所知 可能没有一个程序可以做到这一点 我可能
  • Android Spring Jackson 映射:NoClassDefFoundError

    我试图让我的 Android 应用程序作为 REST 客户端运行 基本上我遵循了这个例子 https github com SpringSource spring android samples tree master spring and
  • 使用概念是否允许在成员函数上使用 decltype

    我来到know https stackoverflow com a 74024419一个班级的X具有名为的成员函数func c 标准不允许我们写decltype X func 因此我预计下面给出的程序会产生一个错误 类似于invalid u
  • 如何在 mac 中使用 Exiftool 添加 GPS 纬度和经度(如何在 jpeg 中编辑元数据)

    我有一堆从 FLIR 相机获得的 jpeg 图像 除了这些图像之外 我还收集了 GPS 坐标 现在我正在尝试将 GPS 纬度和经度获取到图像的元数据中 我用 R 编程语言编写了一个程序 用于查找每个图像相对于时间的 GPS 位置 只要 GP
  • 像 jQuery 插件一样使用 GWT 小部件?

    我可以像 jQuery 插件一样使用 Google GWT 小部件吗 例如 Gwt a css selector mywidget some prefs 也许你正在寻找类似的东西GQuery http code google com p g
  • OpenCV 轮廓矩?

    什么是轮廓矩 有人可以用简单的非数学术语解释这一点吗 可能有一个例子吗 官方的解释是 对轮廓中所有像素进行积分 我不知道什么整合 轮廓矩可以用来做什么 黑色 0 白色 1 的黑白图像的 0 度矩 这只是像素的总和 即白色像素的数量 x 轴和
  • 为什么 C# 中的堆栈大小正好是 1 MB?

    如今的 PC 拥有大量物理 RAM 但 C 的堆栈大小对于 32 位进程仅为 1 MB 对于 64 位进程仅为 4 MB C 中的堆栈容量 https stackoverflow com questions 823724 stack cap