C# NET中的堆栈与堆

C# NET中的堆栈与堆,c#,.net,vb.net,stack,heap,C#,.net,Vb.net,Stack,Heap,在您的实际编程经验中,堆栈和堆的知识在现实生活中是如何拯救您的?有战壕里的故事吗?或者说,这个概念对充实编程书籍和理论都有好处吗?就我个人而言,这是我向我要雇用的每个人提出的为数不多的技术问题之一 我觉得理解如何使用.NET框架(以及大多数其他语言)是至关重要的。我从不雇佣对堆栈和堆上的内存使用情况没有清晰理解的人 如果不理解这一点,就几乎不可能理解垃圾收集器、理解.NET性能特征以及许多其他关键的开发问题。在.NET中,引用类型和值类型的语义之间的区别是一个更重要的概念 就我个人而言,在我多年

在您的实际编程经验中,堆栈和堆的知识在现实生活中是如何拯救您的?有战壕里的故事吗?或者说,这个概念对充实编程书籍和理论都有好处吗?

就我个人而言,这是我向我要雇用的每个人提出的为数不多的技术问题之一

我觉得理解如何使用.NET框架(以及大多数其他语言)是至关重要的。我从不雇佣对堆栈和堆上的内存使用情况没有清晰理解的人


如果不理解这一点,就几乎不可能理解垃圾收集器、理解.NET性能特征以及许多其他关键的开发问题。

在.NET中,引用类型和值类型的语义之间的区别是一个更重要的概念


就我个人而言,在我多年的编码过程中,我从来没有考虑过堆栈或堆(只是基于CLR的)。

我认为,如果你只是在构建普通的业务应用程序,这并不重要,我认为大多数.NET程序员都是这样


我所看到的书只是顺便提到了堆栈和堆,似乎记住这一事实是非常重要的。

在构建编译器时,理解这一区别肯定是有帮助的

以下是我写过的几篇文章,内容涉及内存管理中的各种问题如何影响C#语言和CLR的设计和实现:


重要的区别在于引用类型和值类型之间。“值类型在堆栈上,引用类型在堆上”不是真的。Jon Skeet写过,我们也写过。

我们有一个索赔实体(业务对象),其中包含整个索赔的数据。应用程序的一个要求是为用户更改的每个值创建审计跟踪。为了避免两次访问数据库,我们将在表单中维护原始索赔实体和工作索赔实体。当用户单击“保存”时,工作索赔实体将得到更新,然后我们将原始索赔实体属性与相应的工作索赔实体属性进行比较,以确定更改的内容。有一天,我们注意到,我们的比较方法从未发现差异。这就是我对堆栈和堆的理解保存了我的后端(特别是值类型和引用类型)。因为我们需要在内存中维护相同对象的副本,所以开发人员只创建了两个对象

Dim originalClaim As ClaimBE
Dim workingClaim As ClaimBE
然后调用业务层方法返回claim对象,并将相同的claimBE分配给这两个变量

originalClaim = BLL.GetClaim()
workingClaim = originalClaim

因此,两个引用类型指向相同的值类型。噩梦避免了

对我来说,这是“开发人员/程序员”和“工匠”的区别。任何人都可以学习编写代码,并在不知道原因/方式的情况下看到事情是如何“神奇地发生”的。为了让你的工作真正有价值,我认为尽可能多地了解你正在使用的框架是非常重要的。请记住,它不仅仅是一种语言,它是一个框架,您可以利用它来根据自己的能力创建最佳应用程序

多年来,我分析了许多内存转储,发现了解它们的内部结构和区别非常有用。其中大多数都是由于内存不足和应用程序不稳定而导致的。在查看转储时,使用WinDbg绝对需要这些知识。在调查内存转储时,了解如何在内核/用户模式进程和CLR之间分配内存至少可以告诉您从何处开始分析

例如,让我们以OOM为例: 您在堆大小、工作集、私有内存、共享内存、虚拟内存、提交内存、句柄和线程中看到的已分配内存可以作为从何处开始的重要指标

CLR使用大约8个不同的堆:

  • 加载程序堆:包含CLR结构和类型系统
  • 高频堆:statics、MethodTables、fielddesc、接口映射
  • 低频堆:EEClass、ClassLoader和查找表
  • 存根堆:CAS存根、COM包装器、P/Invoke
  • 大型对象堆:需要超过85k字节的内存分配
  • GC堆:用户分配给应用程序的专用堆内存
  • JIT代码堆:由mscoreee(执行引擎)和JIT编译器为托管代码分配的内存
  • 进程/基本堆:互操作/非托管分配、本机内存等
  • 查找具有高分配的堆可以告诉我是否存在内存碎片、托管内存泄漏、互操作/非托管泄漏等

    知道您为应用程序使用的每个线程分配了1MB(x86上)/4MB(x64上)的堆栈空间,提醒我,如果我有100个线程,您将额外使用100MB的虚拟内存

    我有一个客户机,它的Citrix服务器由于内存不足而崩溃,当他们的应用程序在多个会话中运行时,它不稳定,响应速度慢。在查看转储(我没有访问服务器的权限)之后,我看到该应用程序实例使用了700多个线程!了解线程堆栈分配,使我能够将高线程使用率导致的OOM关联起来


    简言之,由于我为我的“角色”所做的一切,我拥有的知识是无价的。当然,即使你没有调试内存转储,也不会有任何伤害

    这与其说是一个有真实答案的问题,不如说是一个讨论的话题;考虑把它转换成wiki,它似乎更多的是讨论到目前为止发布的答案。这个问题可以回答为“概念没有用”,或者“概念有用,下面是一个如何使用的示例”。没有具体例子的“概念有用”实际上并不能回答这个问题。看这篇文章谈论的是.net的堆栈和堆。我同意你的观点,但你确实没有提供一个好的例子