在这种情况下,“未处理StreamWriter”会导致内存泄漏吗?

3

我有一个方法,具体如下:

public int TranslateOOV(string word, Stream logStream)
{
StreamWriter writer = new StreamWriter(logStream);

//Do some logging
//dont close the writer and leave the caller close the stream
}

我没有关闭StreamWriter,因为调用者应该关闭内部流,这会导致内存泄漏吗?
4个回答

5

只是为了好玩,我打开了反编译器,看看在StreamWriter上Dispose方法的作用(想着也许只需要处理底层流资源)。以下是输出的内容:

protected override void Dispose(bool disposing)
{
    try
    {
        if (this.stream != null)
        {
            if (disposing || (this.Closable || this.stream as __ConsoleStream))
            {
                this.Flush(true, true);
                if (this.mdaHelper != null)
                {
                    GC.SuppressFinalize(this.mdaHelper);
                }
            }
        }
    }
    finally
    {
        if (this.Closable)
        {
            if (this.stream != null)
            {
                if (disposing)
                {
                    this.stream.Close();
                }
                this.stream = null;
                this.byteBuffer = null;
                this.charBuffer = null;
                this.encoding = null;
                this.encoder = null;
                this.charLen = 0;
                base.Dispose(disposing);
            }
        }
    }
}

有点冗长,但我认为这告诉我们的是处理流会处理StreamWriter使用的唯一可处置资源。byteBuffer和charBuffer字段是数组,encoding和encoder不可处置,基本Dispose是虚拟的,因此如果没有清理它,Stream是唯一可能会引起问题的东西。
我认为这也表明,如果您想记录流的内容,并在之后保留其可用状态,则绝对不要处置您的StreamWriter,因为那样会处置Stream(Close调用Dispose(true))。 您还需要确保重置流的位置,因为您无疑会通过读取内容来更改它。 当然,这也意味着您可能要检查流上的CanSeek属性,并确保一旦读取内容,您将能够将位置返回到之前的位置。

我曾经担心泄漏问题,但这个设计正好满足了你所说的要求。 - Ahmed

0
作为最佳实践,您应该在不再需要它时立即关闭它。然而,垃圾回收应该在它离开本地函数范围时将其标记为清理对象。

你没有理解调用者清理流的重点。 - H H
啊,是的,我做错了。我没注意到。对于误解,抱歉。 - BAKeele

0

如果流不再被引用,那么它肯定会被垃圾回收器处理掉,因为它实现了IDisposable接口。
让垃圾回收器处理它的问题在于,它被处理的时间是不确定的,取决于几个条件。
因此,理论上它不会导致内存泄漏,但它会使您的应用程序在更长的时间内使用更多的资源,这可能非常低效。


调用者关闭流。写入器不持有(其他)资源。 - H H

-2

这不是我的强项,但是你应该将StreamWriter放入Using()块中,释放StreamWriter不应该释放流。如果它确实释放了流,你需要返回StreamWriter引用,以便可以进一步清理。

编辑:微软的编码真是太随意了。正如@ckramer的答案所示,StreamWriter不会释放流,而是直接关闭流。深入研究Close方法http://msdn.microsoft.com/en-us/library/system.io.stream.close.aspx

此方法调用Dispose,指定为true以释放所有资源。您不必专门调用Close方法。相反,请确保每个Stream对象都被正确处理。

很高兴看到微软直接忽略了自己的声明。更好的是。

实现者注意事项

在派生类中,不要重写Close方法,而是将所有Stream清理逻辑放在Dispose方法中。

这完全没有意义。他们不仅忽略了他们的第一个陈述,还创建了一个违反开放封闭原则的类,使您能够以可能导致意外场景的方式修改类。对于这样的语句,关闭绝对不应该是虚拟的,或者他们应该纠正考虑此事时的任何推理。


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