簡體   English   中英

ZDecompressStream()導致內存泄漏

[英]ZDecompressStream() causes memory leak

我一直在使用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的調用會從inflateInit分配內存。 它需要與對inflateEnd的調用配對。 因為ZCompressCheck在遇到錯誤時會引發異常,所以對inflateEnd的調用永遠不會發生。 因此代碼泄漏。

使用try / finally正確保護該單元中的inflateInitinflateEnd的其他調用。 它似乎只是在這個函數中使用是錯誤的。

我的建議是用正確實現的版本替換Zlib單元。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM