【发布时间】:2020-03-13 12:38:53
【问题描述】:
我尝试围绕this jpeg 解码器库(Arnaud Bouchez 原创)实现一个包装器。该库速度很快,但并不支持所有 jpeg!
对于非常大的 jpg 文件,它会失败(如预期的那样)并出现 EOutOfResources 异常。
所以我尝试默默地跳过这些文件。它可以工作,但是当我关闭应用程序时,FastMM 表示内存泄漏。
function FastJpgDecode(FileName: string; OUT ErrorType: string): TBitmap;
var Img: PJpegDecode;
res: TJpegDecodeError;
Stream: TMemoryStream;
begin
Result:= NIL;
Stream:= TMemoryStream.Create;
TRY
if Length(FileName) > MAX_PATH then { TMemoryStream does not support long paths }
begin
ErrorType:= 'File name too long!';
Exit;
end;
Stream.LoadFromFile(FileName);
Stream.Position:= 0;
res:= JpegDecode(Stream.Memory, Stream.Size, Img);
case res of
JPEG_SUCCESS:
begin
try
Result:= Img.ToBitmap; // This will raise an EOutOfResources for large files!
except
on EOutOfResources do
ErrorType:= 'JPEG_OUTOFMEM!';
end;
end;
JPEG_EOF : ErrorType:= 'JPEG_EOF!';
JPEG_OUTOFMEM : ErrorType:= 'JPEG_OUTOFMEM!';
JPEG_CPUNOTSUPPORTED : ErrorType:= 'JPEG_CPUNOTSUPPORTED!';
JPEG_BADFILE : ErrorType:= 'JPEG_BADFILE!';
JPEG_FORMATNOTSUPPORTED : ErrorType:= 'JPEG_FORMATNOTSUPPORTED!'; // Not all jpegs are supported. In this case we fall back to WIC or the standard LoadGraph loader (WIC).
end;
FINALLY
Img.Free;
Stream.Free;
END;
end;
function TJpegDecode.ToBitmap: TBitmap;
begin
if @self=nil
then result := nil
else
begin
result := TBitmap.Create;
try
if not ToBitmap(result) // This will raise an EOutOfResources for large files!
then FreeAndNil(result);
except
FreeAndNil(Result);
raise;
end;
end;
end;
内存块已泄漏。尺寸为:36
这个块是由线程 0xD0C 分配的,堆栈跟踪(返回 地址)当时是:407246 40830F 408ADE 43231B [未知 __dbk_fcall_wrapper 处的函数] 407246 40A532 53C353 [未知 TMethodImplementationIntercept 处的函数] 6E006F [未知函数 在 TMethodImplementationIntercept] 7765648F [RtlNtStatusToDosError] 77656494 [RtlNtStatusToDosError] 767A7BEA [未知函数在 IsNLSDefinedString]
该块当前用于类对象:EOutOfResources 分配号为:4181
从指针地址 7EEEA6C0 开始的 256 字节的当前内存转储: 74 7F............ t D . ü $ ú ......
内存块已泄漏。尺寸为:132
该块由线程 0xD0C 分配,堆栈跟踪(返回 地址)当时是:407246 40A2E7 40A518 53C341 [未知 TMethodImplementationIntercept 处的函数] 6E006F [未知函数 在 TMethodImplementationIntercept] 7765648F [RtlNtStatusToDosError] 77656494 [RtlNtStatusToDosError] 767A7BEA [未知函数在 IsNLSDefinedString] 7677F0BA [VirtualQueryEx] 7677F177 [VirtualQuery] 898FD9 [GetFrameBasedStackTrace]该块当前用于类对象:UnicodeString
分配号为:4180
从指针地址 7EFA24F0 开始的 256 字节的当前内存转储: B0 04 02 00 01 00 00 00………… . . . . . . . : . . .不是 。 .足够的存储空间。 .一世 。小号.一种 。诉一种 。一世 。升。一种 。 b .升。 e. .吨。 ○。 .磷。 r 。 ○。 C 。 e. s .小号.吨。 H 。一世 。小号. C 。 ○。米。米。一种 . ñ。 d ....
此应用程序已泄露 记忆。小块泄漏是(不包括注册的预期泄漏 通过指针):
21 - 36 字节:EOutOfResources x 1 117 - 132 字节:UnicodeString x 1
为什么会在那里泄漏内存?
【问题讨论】:
-
看起来有点像异常/错误返回的数据,最终变得孤立。
-
EOutOfMemory- 非常特殊的例外。它包含私有标志AllowFree(默认为 False)。此标志防止创建的异常正常释放。见EHeapException.FreeInstance。这是“正常”的,因为当“正常”内存管理失败时会引发此异常
标签: delphi jpeg delphi-10.3-rio