GC.Collect() and PerformanceCounter

9
我的一位同事认为Oracle的odp.net ado.net实现存在内存泄漏问题。他编写了一个测试程序来验证这个理论,并在调用每个对象的dispose方法后执行以下操作,以确定释放了多少内存:
PerformanceCounter p = new PerformanceCounter("Memory", "Available Bytes");

GC.Collect();
GC.WaitForPendingFinalizers();

float mem = p.NextValue();

生成的性能值随后与在丢弃对象之前检索的值进行比较。这样做会产生准确的结果吗?

你尝试使用ProcessExplorer来监视你的进程中的.NET内存和系统内存使用情况了吗?你没有说明哪种类型的内存正在泄漏... - GregC
10
不,内存管理器不是这样工作的。在分配虚拟内存空间后,它会将释放的块放回空闲块列表中,以备稍后重新使用。 - Hans Passant
我们不知道哪种类型的内存泄漏,这也是测试的一部分,确认是否存在问题。我的问题是确认测试是否有效。 - zaq
为什么我们要使用dispose()方法? - Lijo
1个回答

2
我认为最好的方法是使用GC.GetTotalMemory(true)。您可以在分配对象之前调用它以记录分配了多少内存。然后,创建对象,可能对其执行某些操作,处理它,确保没有对它的引用(可能只需将局部变量设置为null),然后再次调用它。
请注意,返回的值可能不完全准确,根据文档,该方法将返回:

当前在托管内存中分配的字节数的最佳可用近似值。

之后,您可以比较这两个值。如果您反复执行此操作,则可以查看对象是否实际上泄漏了托管内存。
当然,如果对象泄漏了非托管内存,则这种方法无法帮助您。
另一个选择是使用内存分析器,但如果您知道内存可能泄漏的确切位置,则可能过于繁琐。

谢谢你提供了更好的方法来获取结果。这是否意味着我之前的方法有问题?为什么这个方法更好? - zaq
2
是的,你的方法是错误的,请阅读Hans Passant的评论。当CLR收集垃圾时,通常不会将内存返回给系统,因此即使实际上已释放了内存,您可能看不到可用字节数的任何变化。 - svick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接