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

时间:2011-05-31 17:42:37

标签: c# stream dispose

我的方法如下

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 个答案:

答案 0 :(得分:5)

为了好玩,我破解了反编译器以查看Dispose在StreamWriter上做了什么(想想底层流可能是唯一需要处理的资源)。以下是出版的内容:

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使用的唯一Disposable资源。 byteBuffercharBuffer字段是数组,encodingencoder不是一次性的,基数Dispose是虚拟的,因此Stream是唯一的如果没有清理它会引起问题。

我认为这也清楚地表明,如果您想要记录流的内容,并在之后将其保持在可用状态,那么您最挑剔地想要丢弃您的StreamWriter ,因为那会处理Stream(Close calls Dispose(true))。您还需要确保重置Stream的位置,因为您无疑会通过阅读内容来更改它。当然,这也意味着您可能想要检查Stream上的CanSeek属性,并确保一旦您阅读了内容,您就可以将位置返回到之前的位置。

答案 1 :(得分:0)

作为最佳做法,您应该在不再需要它时立即关闭它。但是,垃圾收集应该在离开本地函数范围时将其标记为清理。

答案 2 :(得分:0)

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

答案 3 :(得分:-2)

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

编辑:微软的随意编码。 StreamWriter不会处理流,因为您可以直接在@ckramer的答案中看到它Close流。深入研究密切方法http://msdn.microsoft.com/en-us/library/system.io.stream.close.aspx

  

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

很高兴看到微软直接忽略了他们自己的陈述。它会变得更好。

  

对实施者的说明

     

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

这绝对没有意义。因此,他们不仅忽略了他们的第一个陈述,而且还创建了一个违反开放原则的类,使您能够以可能导致意外情况的方式修改类。对于这样的陈述,Close绝对不应该是虚拟的,或者他们应该修复任何推理进入这个考虑因素。