找回密码
 立即注册
首页 业界区 业界 .NET陷阱之五:奇怪的OutOfMemoryException——大对象堆 ...

.NET陷阱之五:奇怪的OutOfMemoryException——大对象堆引起的问题与对策

琦谓 2025-5-29 16:35:12
我们在开发过程中曾经遇到过一个奇怪的问题:当软件加载了很多比较大规模的数据后,会偶尔出现OutOfMemoryException异常,但通过内存检查工具却发现还有很多可用内存。于是我们怀疑是可用内存总量充足,但却没有足够的连续内存了——也就是说存在很多未分配的内存空隙。但不是说.NET运行时的垃圾收集器会压缩使用中的内存,从而使已经释放的内存空隙连成一片吗?于是我深入研究了一下垃圾回收相关的内容,最终明确的了问题所在——大对象堆(LOH)的使用。如果你也遇到过类似的问题或者对相关的细节有兴趣的话,就继续读读吧。
如果没有特殊说明,后面的叙述都是针对32位系统。
首先我们来探讨另外一个问题:不考虑非托管内存的使用,在最坏情况下,当系统出现OutOfMemoryException异常时,有效的内存(程序中有GC Root的对象所占用的内存)使用量会是多大呢?2G? 1G? 500M? 50M?或者更小(是不是以为我在开玩笑)?来看下面这段代码(参考 https://www.simple-talk.com/dotnet/.net-framework/the-dangers-of-the-large-object-heap/)。
  1. 1 public class Program
  2. 2 {
  3. 3     static void Main(string[] args)
  4. 4     {
  5. 5         var smallBlockSize = 90000;
  6. 6         var largeBlockSize = 1 << 24;
  7. 7         var count = 0;
  8. 8         var bigBlock = new byte[0];
  9. 9         try
  10. 10         {
  11. 11             var smallBlocks = new List<byte[]>();
  12. 12             while (true)
  13. 13             {
  14. 14                 GC.Collect();
  15. 15                 bigBlock = new byte[largeBlockSize];
  16. 16                 largeBlockSize++;
  17. 17                 smallBlocks.Add(new byte[smallBlockSize]);
  18. 18                 count++;
  19. 19             }
  20. 20         }
  21. 21         catch (OutOfMemoryException)
  22. 22         {
  23. 23             bigBlock = null;
  24. 24             GC.Collect();
  25. 25             Console.WriteLine("{0} Mb allocated",
  26. 26                 (count * smallBlockSize) / (1024 * 1024));
  27. 27         }
  28. 28         
  29. 29         Console.ReadLine();
  30. 30     }
  31. 31 }
复制代码
 

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
1.jpeg
2.jpeg
3.gif
4.jpeg
您需要登录后才可以回帖 登录 | 立即注册