加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

delphi – ZDecompressStream()导致内存泄漏

发布时间:2020-12-15 09:15:04 所属栏目:大数据 来源:网络整理
导读:我一直在使用ZLib函数来压缩/解压缩内存中的流.如果我尝试解压缩无效流,它会泄漏内存.以下代码会泄漏内存: uses Winapi.Windows,System.Classes,System.ZLib;function DecompressStream(const AStream: TMemoryStream): Boolean;var ostream: TMemoryStream
我一直在使用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单元.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读