C#/ .Net Framework中的堆大小 - 它可以增长吗?

时间:2014-06-04 16:37:27

标签: c# .net memory-management garbage-collection heap

我在一本大学书中遇到过一个令人困惑的问题: 在那里声明“堆不是静态的,可以根据需要通过从操作系统请求更多内存来增长。”

所以我对此感到困惑的是:假设我运行我的应用程序,并在堆上分配对象。在某些时候,应用程序内存不足:现在发生了什么?

根据我的理解,Gc(垃圾收集器)启动并开始标记和扫描操作。我想知道不管怎样,而不是通过CLR调用Gc,堆是否有可能从操作系统请求更多内存?

我读过用C ++语言,有一种方法可以实现,但在C#.Net Framework 4.5中有可能吗?

5 个答案:

答案 0 :(得分:5)

.Net中的堆是内存的一部分,出于实际目的,32位进程最大可达1.5GB,64位无限(再次出于实用目的),它确实会请求内存根据操作系统的需要。但是由于过多的碎片和大量分配的使用,它可能会耗尽内存 - GC不会压缩大对象堆。

当你在C ++中使用它时,你可以完全控制你想要如何制定内存分配的策略,在.NET中为你完成,你几乎没有说明如何做到这一点,尽管它大部分都做了一个该死的好工作。

答案 1 :(得分:2)

认识an "out of memory" error doesn't mean you're out of physical memory很重要。这意味着您已离开虚拟内存。在32位应用程序中,该应用程序虚拟地址空间中的项目有2 ^ 32个可能的地址。

操作系统负责将该虚拟地址空间的各个部分映射到实际的物理存储介质,无论是RAM,硬盘驱动器还是任何其他存储设备。由于大多数应用程序并未使用其绝大部分虚拟地址空间,因此大部分应用程序都没有映射到任何内容,并且在它们首次开始使用之前并不对应任何内容。

虽然程序可能会随着时间的推移而改变,但虚拟内存的哪些块对应于物理内存的实际块(这是程序一次使用超过2 ^ 32个字的内存所需)所以这种情况并不常见,通常只能由视频处理应用程序等程序完成,这些程序确实需要同时存储大量内存。此过程也是手动。如果您没有手动交换每个虚拟内存块映射到的虚拟内存,即使您仍然拥有能够存储更多信息的存储设备。这是一个Out of Memory错误。

C#应用程序中的堆几乎是堆栈未占用的虚拟地址空间的全部内容,静态字段的存储以及任何其他开销,例如实际的内存程序代码。从应用程序的角度来看,堆从一开始就一直很大。操作系统已经抽象出这样一个事实,即C#运行时几乎所有的东西都被认为是"它的内存"实际上并没有映射到任何地方,因为它没有被使用;当你开始使用更多的堆时,越来越多的堆实际上被映射到某种形式的物理存储。

如果您有64位应用程序,您基本上可以在此答案中将32的所有实例替换为64

答案 2 :(得分:0)

堆是动态的,当你添加到堆中时,它会增长。它在某种意义上为内存中的其他位置创建指针。应用程序在内存不足之前可以占用的内存大小总是有限制的。达到限制时,通常会出现“内存不足”的情况。例外。

阅读维基可能有所帮助:
http://en.wikipedia.org/wiki/Heap_%28data_structure%29
http://en.wikipedia.org/wiki/Heap_%28programming%29#Dynamic_memory_allocation

答案 3 :(得分:0)

堆增长是因为您的应用程序正在分配并保留对象。只要您的应用程序需要存储指向应用程序当前正在使用的对象的指针,堆就会请求内存。

每当您用完堆时,您都会收到错误提示堆内存不可用或类似的内容。为避免此类GC,您可以在实现自己的CLR主机时控制此行为。 please Refer

您可以采取一些措施来限制内存使用量。请参阅此问题以获得一些输入:Reducing Memory usage

要了解有关堆(ing)以及堆栈(ing)的更多信息,请参阅以下链接:

  1. Stack and heap
  2. Large Object Heap Uncovered
  3. Fundamentals of Garbage Collection

答案 4 :(得分:0)

通过将应用程序构建到64位体系结构,您可以分配大于2 GB的内存,这需要您创建新的构建配置。使用普通(默认)"任何CPU"为您的.NET项目构建选项,您的应用程序将始终在32位模式下运行,即使在64位Windows操作系统上也是如此。因此,在应用程序执行期间,您无法分配超过大约1.5到2 GB的RAM内存。要以真正的64位模式运行.NET应用程序,您需要进入构建配置管理器并为x64体系结构创建构建类型,然后使用该构建类型显式重新编译x64程序。可以使用以下步骤为.NET解决方案创建x64构建模式选项:

  1. 在Visual Studio"解决方案资源管理器"窗格,右键单击解决方案图标,然后选择"配置管理器"弹出菜单中的选项。这将打开构建"配置管理器" .NET解决方案文件的对话框窗口。
  2. 在构建的右侧,顶部"配置管理器"对话框,单击向下箭头并选择"< new>"选项。这将打开"新的解决方案平台"对话。
  3. 在"新解决方案平台"对话框,用于"平台"选项,选择" x64"从下拉菜单中。然后单击"确定"现在,Configuration Manager对话框中将显示按钮和新的x64构建选项。
  4. 然后,在"配置管理器"对话框,选择" x64"在" Active Solution Platform"下拉式菜单。点击"关闭"按钮。
  5. 在Visual Studio"解决方案资源管理器"窗格,右键单击CS Project图标,然后选择"属性"弹出菜单中的选项(此菜单底部的最后一个选项)。这将打开CS Project属性窗口。
  6. 在CS Project属性窗口的左侧,单击" Build"选项卡显示代码项目的构建属性。在此窗口的顶部,请注意"平台"现在应该说" x64" (而不是默认的"任何CPU"选项)。如果"平台"下拉菜单不会显示" x64",您应该立即选择它。
  7. 然后只需构建代码并在" bin"文件夹,您现在应该有一个x64文件夹,其中包含您的应用程序的新64位版本。
  8. 在64位Windows操作系统上使用64位版本的应用程序将允许您的程序分配超过〜2GB的内存,大概可达2 ^ 64个地址空间(如果您有RAM和磁盘空间)可用,这是撰写此回复时的真正限制因素)。

    如果您的应用程序中仍然没有内存不足,您还可以增加Windows内存页面文件的大小。在Windows上,页面文件允许操作系统将内存从RAM转移到磁盘(如果RAM内存空间不足)。但是,将RAM内存部分移入和移出磁盘需要花费大量时间,因此它可能会严重影响应用程序的性能。无论性能如何,通过增加页面大小,您(理论上)可以使页面文件与Windows计算机的C:驱动器上的可用空间一样大。在这种情况下,您的应用程序将能够在程序执行期间分配最多4 TB的内存(或页面文件大小设置为的任何内存量)。要更改Windows计算机的页面文件设置,请执行以下操作:

    1. 打开"系统属性"通过右键单击"此PC"并选择"属性"弹出菜单上的选项。这也可以在Windows的更高版本(Windows 10,Win 2012 Server等)中通过转到" Start" > "控制面板" > "系统和安全" > "系统&#34 ;.
    2. 在"系统"的左侧对话框,单击"高级系统属性"选项。这将显示" Advanced"遗产选项卡"系统属性" Windows对话框。
    3. 在"高级"遗产选项卡"系统属性"对话框,单击"设置" " Performance"中的按钮框。这将选择"性能选项"对话。
    4. 关于"表演选项"对话框,点击"高级"选项卡以查看Windows内存页面文件的当前大小设置。
    5. 要增加页面文件大小,请单击"更改"按钮和"虚拟内存"对话框将被打开。
    6. 在"虚拟内存"对话框,选择" C:"然后在"自定义尺寸"下,设置"初始"和"最大"大小。您可以使用C:驱动器上最大可用空间量的任何大小,但进行此更改将为硬盘驱动器上的页面文件保留该空间。
    7. 然后点击"确定"在所有提交新设置的对话框上。然后重新启动计算机以确保所有更改都已正确完成,并且新页面文件设置正在运行。

    无论如何,我希望这有助于人们理解为什么他们会在.NET应用程序中遇到这个1.5-2 GB的内存限制问题,即使在64位Windows机器上运行也是如此。对于人们来说,这可能是一个非常令人困惑的问题,我希望我的解释是有道理的。如果需要,请随时向我发送有关此答案的问题。