简单加载/保存文件时内存泄漏

时间:2014-02-26 00:59:51

标签: c# memory-leaks

作为论文的一部分,我需要加载,修改和保存.dds纹理文件。因此我正在使用DevIL.NET-Wrapper库(但问题并不是特定于这个库我想,这更像是一个普遍问题)。

我管理(通过使用visual studio内存分析工具)来找出DevIL.NET-Wrapper中的内存泄漏函数:

public static byte[] ReadStreamFully(Stream stream, int initialLength) {
        if(initialLength < 1) {
            initialLength = 32768; //Init to 32K if not a valid initial length
        }

        byte[] buffer = new byte[initialLength];
        int position = 0;
        int chunk;

        while((chunk = stream.Read(buffer, position, buffer.Length - position)) > 0) {
            position += chunk;

            //If we reached the end of the buffer check to see if there's more info
            if(position == buffer.Length) {
                int nextByte = stream.ReadByte();

                //If -1 we reached the end of the stream
                if(nextByte == -1) {
                    return buffer;
                }

                //Not at the end, need to resize the buffer
                byte[] newBuffer = new byte[buffer.Length * 2];
                Array.Copy(buffer, newBuffer, buffer.Length);
                newBuffer[position] = (byte) nextByte;
                buffer = newBuffer;
                position++;
            }
        }

        //Trim the buffer before returning
        byte[] toReturn = new byte[position];
        Array.Copy(buffer, toReturn, position);

        return toReturn;
    }

我做了一个测试程序来确定内存泄漏的实际来源:

private static void testMemoryOverflow(string[] args)
    {
        DevIL.ImageImporter im;
        DevIL.ImageExporter ie;

        ...

        foreach (String file in ddsPaths)
        {
            using (FileStream fs = File.Open(file, FileMode.Open))
            {
                /* v  memory leak  v */

                DevIL.Image img = im.LoadImageFromStream(fs);

                /* ^  memory leak  ^ */

                ie.SaveImage(img, fileSavePath);
                img = null;
            }

        }

    }

LoadImageFromStream()函数也是DevIL.NET-Wrapper的一部分,实际上是从上面调用函数。这是泄漏发生的地方。

我已经尝试过:

  • 使用GC.Collect()
  • 手动处理FileStream对象,而不是使用using {}指令
  • 从上面
  • 处理DevIL.NET ReadStreamFully()函数中的流

有人有解决方案吗? 我是C#的新手,所以也许这是一个基本的错误。

1 个答案:

答案 0 :(得分:2)

您的问题是缓冲区大小。

byte[] newBuffer = new byte[buffer.Length * 2];

经过2次迭代..你已经非常接近撞击大对象堆的85K极限。在3次迭代......你已达到门槛。一旦那里......直到所有世代都发生了完整的垃圾收集,它们才会被收集。即便如此...... LOH还没有被压缩..所以你仍会看到一些高记忆。

我不确定您使用的库为何会这样做。我不确定你为什么要使用它......鉴于你可以使用:

Image img = Image.FromStream(fs); // built into .NET.

编写库的方式看起来像是早期版本的.NET。它似乎没有内存使用任何问题。