查找内存泄漏

时间:2018-07-24 15:09:21

标签: c#

我对以下代码有疑问。我在GetDB函数中创建了一个内存流,并在 using 块中使用了返回值。由于某种未知的原因,如果我转储对象,我会发现MemoryStream在Main方法的末尾仍然存在。这导致我大量泄漏。知道如何清洁该缓冲区吗?

我实际上检查了MemoryStream上是否已调用Dispose方法,但是该对象似乎仍然存在,我已使用Visual Studio 2017的诊断工具来完成此任务。

class Program
{
    static void Main(string[] args)
    {
        List<CsvProduct> products;
        using (var s = GetDb())
        {
            products = Utf8Json.JsonSerializer.Deserialize<List<CsvProduct>>(s).ToList();
        }
    }

    public static Stream GetDb()
    {
        var filepath = Path.Combine("c:/users/tom/Downloads", "productdb.zip");
        using (var archive = ZipFile.OpenRead(filepath))
        {
            var data = archive.Entries.Single(e => e.FullName == "productdb.json");
            using (var s = data.Open())
            {
                var ms = new MemoryStream();
                s.CopyTo(ms);
                ms.Seek(0, SeekOrigin.Begin);
                return (Stream)ms;
            }
        }
    }
}

1 个答案:

答案 0 :(得分:3)

  

由于某种未知的原因,如果我转储对象,我会发现MemoryStream仍然在Main方法的末尾。

这不是特别的异常; GC单独发生。

  

这导致我大量泄漏。

这不是泄漏,而只是内存使用情况。

  

有什么主意我可以清理这个缓冲区吗?

我可能只是不使用MemoryStream ,而是返回一些包裹实时解压缩流的内容(来自s = data.Open())。但是,这里的问题是您不能仅仅返回s-因为archive在离开方法时仍然会被处理掉。因此,如果需要解决此问题,我将创建一个自定义Stream,该自定义文件class MyStream : Stream { private readonly Stream _source; private readonly IDisposable _parent; public MyStream(Stream, IDisposable) {...assign...} // not shown: Implement all Stream methods via `_source` proxy public override void Dispose() { _source.Dispose(); _parent.Dispose(); } } 包装一个内部流,并在处理时处理第二个对象,即

public static Stream GetDb()
{
    var filepath = Path.Combine("c:/users/tom/Downloads", "productdb.zip");
    var archive = ZipFile.OpenRead(filepath);
    var data = archive.Entries.Single(e => e.FullName == "productdb.json");
    var s = data.Open();
    return new MyStream(s, archive);
}

然后有:

archive

(如果在我们成功返回之前发生异常,可以稍作改进以确保处置Dim pvt As PivotTable Set pvt = ActiveSheet.PivotTables("PivotTable1") ActiveSheet.PivotTables("PivotTable1").AllowMultipleFilters = True With pvt.PivotFields("Heading 1") .ClearAllFilters .PivotFilters.Add2 Type:=xlValueIsGreaterThan, DataField:=ActiveSheet.PivotTables("PivotTable1").PivotFields("Sum of Heading 2"), Value1:=2 End With With pvt.PivotFields("Help 1") .ClearAllFilters .PivotFilters.Add2 Type:=xlValueIsSmallerThan, DataField:=ActiveSheet.PivotTables("PivotTable1").PivotFields("Sum of Heading 2"), Value1:=11 End With With pvt.PivotFields("Help 2") .ClearAllFilters .PivotFilters.Add2 Type:=xlValueIsGreaterThan, DataField:=ActiveSheet.PivotTables("PivotTable1").PivotFields("Sum of Heading 3"), Value1:=4 End With