Kev*_*ith 5 c# garbage-collection
静态分析工具不断告诉我,我的C#代码中有资源泄漏.
这是一个例子:
StringReader reader = new StringReader(...);
// do something with reader
...
} // static analysis tool cries that I've leaked **reader**
Run Code Online (Sandbox Code Playgroud)
我的工具是否正确?如果是这样,为什么?
编辑(回复评论) - 我的静态分析工具说我有一堆资源泄漏.我从这个论坛知道需要显式释放某些Java AWT对象,否则会发生泄漏.是否需要明确释放C#对象?
Dar*_*rov 13
是的,你的代码泄漏严重.它应该是这样的:
using (StringReader reader = new StringReader(...))
{
}
Run Code Online (Sandbox Code Playgroud)
每个实现的类都IDisposable需要包装在一个using块中,以确保Dispose始终调用该方法.
更新:
Elaborating:在.NET中有IDisposable接口,它定义了Dispose方法.实现此接口的类(如文件流,数据库连接,读取器......)可能包含指向非托管资源的指针,并且确保释放这些非托管资源/句柄的唯一方法是调用Dispose方法.所以在.NET中确保即使抛出异常也会调用某些代码是使用try/finally语句:
var myRes = new MyResource(); // where MyResource implements IDisposable
try
{
myRes.DoSomething(); // this might throw an exception
}
finally
{
if (myRes != null)
{
((IDisposable)myRes).Dispose();
}
}
Run Code Online (Sandbox Code Playgroud)
编写C#代码的人很快就意识到每次处理可处理资源时写这个都是PITA.所以他们引入了using声明:
using (var myRes = new MyResource())
{
myRes.DoSomething(); // this might throw an exception
}
Run Code Online (Sandbox Code Playgroud)
这有点短.
在这种特定情况下,你的代码实际上没有泄漏任何东西,因为StringReader没有任何资源可以清理,就像MemoryStream没有.(随着MemoryStream你可以仍然最终需要处置的,如果你使用它异步远程处理或它......但在简单的情况下,它并不重要.)
但是,处理IDisposable原则上实现的任何东西都是一个好主意.这样可以避免泄漏(可能是暂时的)非托管资源,例如文件句柄.
例如,假设您将代码更改为:
StreamReader reader = new StreamReader("file.txt");
...
Run Code Online (Sandbox Code Playgroud)
如果你不在reader这里关闭或处理(在一个finally块或通过一个using语句)它将保持文件打开,直到任何类型直接持有OS文件句柄最终确定.明确地处理事物不仅可以更早地释放非托管资源 - 它还可以将最终化对象从终结队列中取出,这意味着它们可以在之前进行垃圾回收.