.net 收集仍在作用域中的对象- GC,

8fq7wneg  于 2023-11-20  发布在  .NET
关注(0)|答案(2)|浏览(109)

我读过这篇文章:https://devblogs.microsoft.com/oldnewthing/20100810-00/?p=13193,老实说,我不明白每一个细节。据我所知,在下面的代码c应该被收集,即使我不设置cnull。另一件事是,在foreach期间发生的分配似乎不会被释放,只要我们在同一函数的范围内。(见下面的例子)

  1. class Program
  2. {
  3. public class SomeClass
  4. {
  5. public byte[] X;
  6. public SomeClass()
  7. {
  8. X = new byte[1024 * 1024 * 100];
  9. X[155] = 10;
  10. }
  11. }
  12. static void Main()
  13. {
  14. Console.WriteLine("Memory: " + GC.GetTotalMemory(false));
  15. SomeClass c;
  16. c = new SomeClass();
  17. Console.WriteLine("Memory: " + GC.GetTotalMemory(false));
  18. GC.Collect();
  19. Console.WriteLine("Memory: " + GC.GetTotalMemory(true));
  20. Console.ReadKey();
  21. /* Output:
  22. *
  23. * Memory: 186836
  24. * Memory: 105044468
  25. * Memory: 104963676
  26. */
  27. }
  28. }

字符串

EDIT第一个例子的解决方案:调试器模式(不是在调试器中运行,而是在编译模式下运行)。如果我使用Release,它会像预期的那样工作:即使没有设置为null,也会收集c。对于第二个例子,同样适用。

二示例

  1. static void Main(string[] args)
  2. {
  3. Console.WriteLine("Startup Memory: " + GC.GetTotalMemory(false));
  4. var obj = BOObject.Get();
  5. Console.WriteLine("Fetched Object: " + GC.GetTotalMemory(false));
  6. GC.Collect();
  7. Console.WriteLine("Fetched Object (Collected): " + GC.GetTotalMemory(false));
  8. foreach (var node in obj.Traverse())
  9. {
  10. string name = node.Name;
  11. }
  12. Console.WriteLine("Traversed: " + GC.GetTotalMemory(false));
  13. GC.Collect();
  14. Console.WriteLine("Traversed (collected): " + GC.GetTotalMemory(false));
  15. obj = null;
  16. GC.Collect();
  17. Console.WriteLine("collected: " + GC.GetTotalMemory(true));
  18. Console.Read();
  19. }


输出量:

  1. Startup Memory: 193060
  2. Fetched: 8972464
  3. Fetched (Collected): 5594308
  4. Traversed: 272553096
  5. Traversed (collected): 269564660
  6. collected: 269564048


如果我把foreach循环放在另一个函数中并调用这个函数,那么在调用.Collect之后使用的内存大约是5800000。那么为什么当我在同一个函数中有foreach循环时,垃圾没有被收集呢?

mw3dktmi

mw3dktmi1#

在Raymond文章的评论和Yun Jin的MSDN文章here中提到,
事实上,对于可调试代码,JIT将每个变量的生存期延长到函数结束。
因此,您的收藏不会像您所发现的那样在发布模式下收集,以及为什么它将在发布模式下收集。

n8ghc7c1

n8ghc7c12#

垃圾收集器的行为不是确定性的,也不应该被期望是确定性的。不要依赖GC。
你问的是为什么GC在给定的时间点收集你的垃圾。更好的问题是为什么它**在给定的时间点收集。

相关问题