gpt4 book ai didi

delphi - ZDecompressStream() 导致内存泄漏

转载 作者:行者123 更新时间:2023-12-03 15:30:39 25 4
gpt4 key购买 nike

我一直在使用 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。因此代码泄漏。

该单元中对 inflateInitinflateEnd 的其他调用均受到 try/finally 的正确保护。看来这个函数的使用是错误的。

我的建议是您将 Zlib 单元替换为正确实现的版本。

关于delphi - ZDecompressStream() 导致内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19852941/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com