检测“泄漏” I一次性对象
有很多问题询问如何检测 IDisposable 对象泄漏。答案似乎是“你不能”。
我刚刚检查了最简单的测试用例,FxCop 10.0 没有这样做,带有 MSVS2010 的 ReSharper 4 也没有这样做。
这对我来说似乎是错误的,比 C 中的内存泄漏更糟糕(至少我们已经建立了检测工具)。
我在想:是否有可能,使用反射和其他晦涩的高级技术,我可以在运行时在终结器中注入检查以查看 Dispose
是否已被调用?
WinDBG+SOS 的魔术怎么样?
即使没有现有的工具可以做到这一点,我也想知道这在理论上是否可行(我的 C# 不是很敏锐)。
有想法吗?
注意这个问题的标题可能具有误导性。这里真正的问题应该是IDisposable
对象是否已正确Dispose()
。被 GC 处理掉不算数,因为我认为这是一个错误。
编辑:解决方案:.NET Memory Profiler 可以完成这项工作。我们只需要在程序结束时发送几个GC.Collect()
,以使我们的分析器能够正确获取统计信息。
There are many questions SO asking how to detect IDisposable objects leak. It seems like the answer is "you can't".
I just checked with the most trivial test case, that FxCop 10.0 doesn't do it, ReSharper 4 with MSVS2010 doesn't do it.
This seems wrong to me, worse than memory leaks in C (for which at least we have established tools to detect).
I was thinking: Is it possible, using reflection and other obscure advanced techniques, that I can inject a check at runtime, in the finalizer to see whether Dispose
has been called?
How about magic tricks with WinDBG+SOS?
Even if there aren't existing tools to do it, I'd like to know whether this is theoretically possible (my C# isn't very sharp).
Ideas?
NOTE This question's title might have been misleading. The real question here should be whether a IDisposable
object has been Disposed()
properly. Getting disposed by the GC doesn't count since I regard that as a mistake.
Edit: Solution: .NET Memory Profiler does the job. We just need to spam several GC.Collect()
at the end of the program to enable our profiler to correctly pick up the stats.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
你搜索得不够努力。有很多 .NET 内存分析器可以在程序运行时查看您的程序,并让您知道内存在何处/如何使用(以及泄漏的情况)。
我会检查以下任何内容:
Microsoft 的 CLR 内存分析器(免费)
RedGate ANTS 内存分析器
JetBrain 的 DotTrace(还包括代码分析器)
SciTech .NET Memory Profiler
更新
SciTech 的 .NET Memory Profiler 有一个名为“ Dispose Tracker' 符合 OP 仅跟踪其应用程序中的 Dispose 调用的请求。
You didn't search hard enough. There are plenty of .NET Memory Profilers out there that will look at your program as it runs and let you know where/how your memory is used (and what is leaking it).
I would check out any of the following:
Microsoft's CLR Memory Profiler (free)
RedGate ANTS Memory Profiler
JetBrain's DotTrace (includes code profiler as well)
SciTech .NET Memory Profiler
Update
SciTech's .NET Memory Profiler has a feature called 'Dispose Tracker' that fits the bill for the OP's request of tracking only the Dispose calls in their application.
您可以通过向 IDisposable 对象添加 Finalizer 来做到这一点。
在终结器中,您可以检查对象是否已被释放。如果它还没有被处理,您可以断言这一点,或者向日志中写入一些内容,或者其他什么。
例如,您可以将此功能纳入基类 -
Disposable
- 中,该基类可用作实现 一次性 模式。像这样,例如:
you can do it, by adding a Finalizer to your IDisposable objects.
In the finalizer, you can check whether the object has been disposed or not. If it hasn't been disposed, you can assert this, or write something to a log, or whatever.
You can factor this functionality into a base class -
Disposable
- for instance, which can be used as a template to implement the Disposable pattern for instance.Like this, for instance:
虽然 @Justin Niessner 的建议有效,但我发现使用完整的分析器太重了。
我创建了我的自制解决方案:EyeDisposable。它对程序集进行检测,以检测何时未调用 Dispose。
While @Justin Niessner's recommendation works, I find that using a full blown profiler too heavy.
I created my home-brew solution: EyeDisposable. It instruments assemblies to detect when
Dispose
have not been called.