Bitmap.Save,巨大的内存泄漏

时间:2009-05-16 03:22:02

标签: c# memory-leaks bitmap

我有一个应用程序,我正在使用位图并使用GZipStream压缩它并通过套接字将其发送到内存中。我已经将脏的scumbag内存泄漏跟踪到以​​下行:

frame.Save(inStream, jpegCodec, parameters);

浏览好信息高速公路我已经在各种编解码器的保存方法中发现了许多关于Image类泄漏内存的主题。问题是我找不到任何修复方法。所以我的问题如下:

  1. 是什么导致此
  2. 我该如何解决?
  3. 这是我的FrameStream类中的完整Write()方法,其中包含泄漏。

    /// <summary>
        /// Writes a frame to the stream
        /// </summary>
        /// <param name="frame">The frame to write</param>
        public void Write(Bitmap frame) {
            using (EncoderParameter qualityParameter = new EncoderParameter(Encoder.Quality, 50L)) {
                using (EncoderParameters parameters = new EncoderParameters(1)) {
                    parameters.Param[0] = qualityParameter;
    
                    ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
                    ImageCodecInfo jpegCodec = null;
    
                    foreach (ImageCodecInfo codec in codecs) {
                        if (codec.MimeType == "image/jpeg") {
                            jpegCodec = codec;
                            break;
                        }
                    }
    
                    using (MemoryStream inStream = new MemoryStream()) {
                        frame.Save(inStream, jpegCodec, parameters); // HUUUGE Memory Leak
                        Byte[] buffer = new Byte[inStream.Length];
                        inStream.Read(buffer, 0, buffer.Length);
    
                        using (MemoryStream outStream = new MemoryStream()) {
                            using (GZipStream gzipStream = new GZipStream(outStream, CompressionMode.Compress)) {
                                gzipStream.Write(buffer, 0, buffer.Length);
                            }
    
                            Byte[] frameData = outStream.ToArray();
                            Byte[] packet = new Byte[15 + frameData.Length];
                            Byte[] frameLength = BitConverter.GetBytes(frameData.Length);
    
                            Array.Copy(frameLength, 0, packet, 0, frameLength.Length);
                            Array.Copy(frameData, 0, packet, 15, frameData.Length);
    
                            m_Socket.Send(packet);
                        }
                    }
                }
            }
        }
    

5 个答案:

答案 0 :(得分:4)

我建议在CLR Profiler下运行您的代码以找到泄漏源。如果它是任何类型的托管对象(甚至是非托管资源),只要该漏洞不是由于托管类型泄漏非托管句柄,您就能够看到泄漏的位置。如果它在框架代码中,您可以使用反射和P / Invoke解决它。

例如,在某些情况下,Icon类型会泄漏Win32 HICON。解决方法是使用HICON公开的句柄,通过PInvoking DeleteObject函数手动处理Icon

答案 1 :(得分:3)

好的,在尝试了每个人的想法和想法以及许多其他方法之后。我终于尝试了这么简单:

using (frame) {
    frame.Save(outStream, jpegCodec, parameters);
}

好吧,这个工作并且内存泄漏是固定的。我试图强制调用垃圾收集器,手动处理位图,使用P / Invoke DeleteObject,没有任何效果,但是使用了using语句。所以这让我想知道在我错过的使用陈述中会发生什么事情......

答案 2 :(得分:2)

处理完毕后,您应该将位图设置为null。

此外,您可能希望在处理Bitmap后调用垃圾收集器(即使这是一项昂贵的操作):GC.Collect();

Bitmap保存非托管资源 - GC并不总是“在球上”。这是一个关于Bitmap类的有趣链接(从紧凑框架的角度来看):http://blog.opennetcf.com/ctacke/PermaLink,guid,987041fc-2e13-4bab-930a-f79021225b74.aspx

答案 3 :(得分:0)

我对套接字知之甚少。但是,我知道使用Image类来阻止内存泄漏的一种方法是冻结位图。希望this post可能会为您提供更多信息。 MemoryStream.Dispose会失败吗?从而,造成内存泄漏。

答案 4 :(得分:0)

您是否正在调用Graphics对象的.Dispose()方法? 导致内存泄漏。编辑:一旦你写了字节[],你现在可以清楚地看到Bitmap对象的.Dispose()。