c# - 无法确定第 2 代对象引用的来源

标签 c# memory-leaks garbage-collection

昨天我决定尝试一下国际象棋程序,因为多年来我意识到我从未编写过国际象棋程序。我创建了一个人工智能来评估许多可能的移动/位置并消耗大量内存。但我想如果我每回合都切断对这些数据的引用就可以了。我应该在需要的时候恢复内存。但由于某种原因,这些对象被保留在内存中。即使当我调用 GC.Collect() 时,我发现内存使用量并没有下降,而且,这要归功于 GC 的新 GetGeneration 方法我可以看到我的对象停留在第 2 代(当然,我使用弱引用来保留它们,以便传递给 GetGeneration)。代码并不像人们想象的带有人工智能的国际象棋程序那么大。位于https://github.com/bluemonkmn/Chess 。在本地,我更改了 Program.cs 文件以对本地 board 变量进行弱引用。然后我有一些代码来尝试消除我的引用并检查垃圾收集:

board = board.Clone();
validMoves.Clear();
Console.WriteLine(GC.GetGeneration(wr));
GC.Collect(2);
GC.WaitForFullGCComplete();
GC.WaitForPendingFinalizers();
Console.WriteLine(GC.GetGeneration(wr));

Clone 函数(如果您愿意,您可以在原始项目中看到 - 上面链接)应该制作一个副本,而不引用旧数据。我找不到任何其他对旧对象的引用。然而,对 GC.GetGeneration(wr) 的两次调用都输出 2。这个程序的数据结构看起来并没有那么复杂。我在主函数中没有那么多变量,因此不难追踪它们并查看可以保存哪些引用。对旧板对象的引用可能来自哪里?

据我所知,唯一可以直接或间接引用 ChessBoard 对象的变量是 board 变量在 Program.csPlay 函数中。其他一切都使用纯 .NET 框架类型,无法引用我的任意类型。

最佳答案

阅读后What is a "rooted reference"?我发现 Debug模式下的引用根系可能与 Release模式下的不同。我发现当我在没有附加调试器的情况下以 Release模式运行时,所有内存都被返回。它在 Release模式下的运行速度也明显加快。我一直预计 Release模式和 Debug模式之间会存在一些差异,但这是我第一次看到内存使用和性能方面存在如此显着的差异。

关于c# - 无法确定第 2 代对象引用的来源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27694015/

相关文章:

c# - 该进程无法访问该 exe 文件,因为它正被另一个进程使用

javascript - Bing Maps V8 JS API 内存泄漏问题

java - 为什么 New Relic 会占用大量 tomcat 内存?

java - 使用多个线程是不好的做法吗? (通过 SwingWorkers)

c# - 获得距离今天的周数

c# - Socket.Shutdown 和线程

c++ - 堆栈展开动态创建的对象,其构造函数也作用于堆

objective-c - 如何确定已编译的 Objective-C 应用程序是否正在使用垃圾回收?

for循环中的Javascript内存使用

c# - 打印具有空节点的二叉树