我的代码在哪里泄漏?

时间:2009-05-18 11:52:42

标签: c# file memory-leaks

这是我的代码,它打开XML文件(old.xml),过滤无效字符并写入另一个XML文件(abc.xml)。最后,我将再次加载XML(abc.xml)。执行跟随行时,有异常说xml文件由另一个进程使用

xDoc.Load("C:\\abc.xml");

有没有人有任何想法有什么不对?我的代码中有任何泄漏以及为什么(我一直在使用“使用”关键字,看到泄漏感到困惑......)

这是我的整个代码,我在Windows Vista x64下使用C#+ VSTS 2008。

    // Create an instance of StreamReader to read from a file.
    // The using statement also closes the StreamReader.
    Encoding encoding = Encoding.GetEncoding("utf-8", new EncoderReplacementFallback(String.Empty), new DecoderReplacementFallback(String.Empty));
    using (TextWriter writer = new StreamWriter(new FileStream("C:\\abc.xml", FileMode.Create), Encoding.UTF8))
    {
        using (StreamReader sr = new StreamReader(
            "C:\\old.xml",
            encoding
            ))
        {
            int bufferSize = 10 * 1024 * 1024; //could be anything
            char[] buffer = new char[bufferSize];
            // Read from the file until the end of the file is reached.
            int actualsize = sr.Read(buffer, 0, bufferSize);
            writer.Write(buffer, 0, actualsize);
            while (actualsize > 0)
            {
                actualsize = sr.Read(buffer, 0, bufferSize);
                writer.Write(buffer, 0, actualsize);
            }
        }
    }

    try
    {
        XmlDocument xDoc = new XmlDocument();
        xDoc.Load("C:\\abc.xml");
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }

EDIT1:我试图将缓冲区的大小从10M更改为1M,它可以工作!我很困惑,有什么想法吗?

EDIT2:我发现当输入的旧XML文件非常大时,例如100M或其他东西,这个问题很容易重现。我怀疑它是否是.Net已知错误?我将使用ProcessExplorer / ProcessMonitor等工具来查看哪个进程锁定文件以防止XmlDocument.Load访问该文件。

11 个答案:

答案 0 :(得分:4)

这对我来说很好。 纯粹猜测,但也许病毒检查员正在扫描文件? 要进行调查,请尝试禁用病毒检查程序并查看其是否有效(然后重新启用病毒检查程序)。

顺便说一下,可以让文件保持打开的一种方式:如果StreamReader构造函数抛出异常;但是,无论如何你都不会达到XmlDocument的东西......但请考虑:

using (FileStream fs = new FileStream("C:\\abc.xml", FileMode.Create))
using (TextWriter writer = new StreamWriter(fs, Encoding.UTF8))
{
   ...
}

现在fs处于new StreamWriter(...)抛出的边缘情况中。但是,我认为这是问题所在。

答案 1 :(得分:2)

您可能在根目录上运行FileSystemWatcher?

您还可以使用ProcessMonitor查看访问该文件的人员。

答案 2 :(得分:2)

问题是你的char[]似乎很大。如果它太大,它位于大型objekt堆上,而不是堆栈上。因此,只要软件正在运行,大型对象堆就不会被压缩,一旦分配的空间可能不会再次使用 - 这看起来像是内存泄漏。尝试将阵列拆分为较小的块。

答案 3 :(得分:2)

我的第二个Leppie建议使用ProcessMonitor(或等效的)来确定谁锁定文件。其他任何事情都只是猜测。

答案 4 :(得分:1)

您的缓冲区未被释放,是吗?

答案 5 :(得分:1)

代码工作正常。刚检查过。

答案 6 :(得分:1)

使用会调用Dispose,但Dispose会在写入流上调用close吗?如果没有,系统仍可以认为该文件是开放的。

我会尝试在其writer块结束之前结束using

编辑:我自己也试过了代码。编译并运行没有你看到的问题。尝试像其他人提到的那样关闭病毒扫描程序,并确保在文件打开的地方没有窗口。

答案 7 :(得分:1)

您是否检查过没有其他进程尝试访问该文件?

答案 8 :(得分:1)

它适用于某些人而不适用于其他人的事实使我认为该文件未被关闭。在尝试加载文件之前关闭编写器。

答案 9 :(得分:1)

我敢打赌,你有一些防病毒解决方案正在运行,它会在文件关闭后锁定。要进行验证,请尝试在加载文件之前添加延迟(例如,1秒)。如果可行的话,你可能找到了原因。

答案 10 :(得分:0)

运行Process Explorer

确保您的程序首先锁定文件。