我一直在使用ZLib函数来压缩/解压缩内存中的流.如果我尝试解压缩无效流,它会泄漏内存.以下代码会泄漏内存:
uses Winapi.Windows,System.Classes,System.ZLib; function Decompressstream(const AStream: TMemoryStream): Boolean; var ostream: TMemoryStream; begin ostream := TMemoryStream.Create; try AStream.Position := 0; // ISSUE: Memory leak happening here try ZDecompressstream(AStream,ostream); except Exit(FALSE); end; AStream.Clear; ostream.Position := 0; AStream.copyFrom(ostream,ostream.Size); result := TRUE; finally ostream.Free; end; end; var s: TMemoryStream; begin ReportMemoryLeaksOnShutdown := TRUE; s := TMemoryStream.Create; try Decompressstream(s); finally s.Free; end; end.
我尝试在这里解压缩空TMemoryStream,并在执行结束时显示内存泄漏发生.在Delphi XE2上进行测试.
任何想法如何防止这种泄漏发生,因为在现实世界中,我的应用程序有可能尝试解压缩无效流并泄漏内存.
质量控制:http://qc.embarcadero.com/wc/qcmain.aspx?d=120329 – 声称从XE6开始固定
解决方法
这是Delphi RTL代码中的一个错误. ZDecompressstream的实现引发异常,然后无法执行整理.我们来看看代码:
procedure ZDecompressstream(inStream,outStream: TStream); const bufferSize = 32768; var zstream: TZStreamRec; zresult: Integer; inBuffer: TBytes; outBuffer: TBytes; inSize: Integer; outSize: Integer; begin SetLength(inBuffer,BufferSize); SetLength(outBuffer,BufferSize); FillChar(zstream,SizeOf(TZStreamRec),0); ZCompressCheck(InflateInit(zstream)); <--- performs heap allocation inSize := inStream.Read(inBuffer,bufferSize); while inSize > 0 do begin zstream.next_in := @inBuffer[0]; zstream.avail_in := inSize; repeat zstream.next_out := @outBuffer[0]; zstream.avail_out := bufferSize; ZCompressCheck(inflate(zstream,Z_NO_FLUSH)); // outSize := zstream.next_out - outBuffer; outSize := bufferSize - zstream.avail_out; outStream.Write(outBuffer,outSize); until (zstream.avail_in = 0) and (zstream.avail_out > 0); inSize := inStream.Read(inBuffer,bufferSize); end; repeat zstream.next_out := @outBuffer[0]; zstream.avail_out := bufferSize; zresult := ZCompressCheck(inflate(zstream,Z_FINISH)); // outSize := zstream.next_out - outBuffer; outSize := bufferSize - zstream.avail_out; outStream.Write(outBuffer,outSize); until (zresult = Z_STREAM_END) and (zstream.avail_out > 0); ZCompressCheck(inflateEnd(zstream)); <--- tidy up,frees heap allocation end;
我从我的XE3中获取了这个,但我相信它在所有版本中基本相同.我突出了这个问题.对inflateInit的调用会从堆中分配内存.它需要与对inflateEnd的调用配对.因为ZCompressCheck在遇到错误时会引发异常,所以对inflateEnd的调用永远不会发生.因此代码泄露.
使用try / finally正确保护该单元中的inflateInit和inflateEnd的其他调用.它似乎只是在这个函数中使用是错误的.
我的建议是用正确实现的版本替换Zlib单元.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。