gpt4 book ai didi

multithreading - 来自线程的同步事件 - 内存泄漏

转载 作者:行者123 更新时间:2023-12-03 19:16:48 24 4
gpt4 key购买 nike

我试图找到来自线程的内存泄漏的来源。线程重复触发同步事件,返回一个受线程保护的对象。

我通过调用一个过程在线程内触发这个事件......

procedure TDeskMonThread.DoOnImage(const ID: Integer; const R: TRect;
ABmp: TLockBmp);
begin
FSyncOnImageID:= ID;
FSyncOnImageRect:= R;
FSyncOnImageBmp:= ABmp;
Synchronize(SYNC_OnImage);
end;

3 个私有(private)字段仅用于此目的 - 用于事件触发器的临时存储。 TLockBmp只是一个 TBitmap 的包装器带有关键部分,需要锁定和解锁。

然后,同步调用此过程:
procedure TDeskMonThread.SYNC_OnImage;
begin
if Assigned(FOnImage) then //trigger event
FOnImage(FSyncOnImageID, FSyncOnImageRect, FSyncOnImageBmp);
end;

并且此事件由以下过程处理:
procedure TfrmMain.ThreadOnImage(const ID: Integer; const R: TRect;
ABmp: TLockBmp);
var
B: TBitmap;
begin
if ID = FCurMon then begin //Only draw if it's the current monitor
B:= ABmp.Lock;
try
FBmp.Assign(B); //Copy bitmap over
finally
ABmp.Unlock; //Hurry and unlock so thread can continue its work
end;
ResizeBitmap(FBmp, pbView.ClientWidth, pbView.ClientHeight, clBlack);
pbView.Canvas.Draw(0, 0, FBmp); //Draw to canvas
end;
end;

现在我把范围缩小到 ResizeBitmap因为当我注释掉那行代码时,我没有得到内存泄漏。这是该程序:
procedure ResizeBitmap(Bitmap: TBitmap; Width, Height: Integer; Background: TColor);
var
R: TRect;
B: TBitmap;
X, Y: Integer;
begin
if assigned(Bitmap) then begin
B:= TBitmap.Create;
try
if Bitmap.Width > Bitmap.Height then begin
R.Right:= Width;
R.Bottom:= ((Width * Bitmap.Height) div Bitmap.Width);
X:= 0;
Y:= (Height div 2) - (R.Bottom div 2);
end else begin
R.Right:= ((Height * Bitmap.Width) div Bitmap.Height);
R.Bottom:= Height;
X:= (Width div 2) - (R.Right div 2);
Y:= 0;
end;
R.Left:= 0;
R.Top:= 0;
B.PixelFormat:= Bitmap.PixelFormat;
B.Width:= Width;
B.Height:= Height;
B.Canvas.Brush.Color:= Background;
B.Canvas.FillRect(B.Canvas.ClipRect);
B.Canvas.StretchDraw(R, Bitmap);
Bitmap.Width:= Width;
Bitmap.Height:= Height;
Bitmap.Canvas.Brush.Color:= Background;
Bitmap.Canvas.FillRect(Bitmap.Canvas.ClipRect);
Bitmap.Canvas.Draw(X, Y, B);
finally
B.Free;
end;
end;
end;

内存泄漏消息让我感到困惑:

enter image description here
x 3取决于它运行了多长时间,但不是迭代次数。例如,线程可能重复 20 次迭代并显示 x 3或者可以重复 10 次迭代并显示 x 7但我什至找不到与迭代次数相比有多少泄漏的模式。似乎这发生在随机时刻,而不是每次迭代。

所以我开始调试 ResizeBitmap程序,但是当我自己运行它时,即使是反复快速地运行,我也从来没有遇到任何内存泄漏。这似乎与从线程重复调用它有关。我知道它正在创建/销毁 TBitmap 的实例这可能不是最佳实践,但是,当它被线程重复调用时,我只会得到这个内存泄漏。我假设有一个隐藏的异常(资源不足),它实际上从未引发异常 - 因此被困为内存泄漏。

这种内存泄漏可能来自哪里?我该如何预防?

最佳答案

EOutOfResources没有自己的构造函数,因此请尝试在 Exception 的各种构造函数中放置条件断点只有在 self.ClassType = EOutOfResources 时才会触发.然后您将找到创建异常对象的点,并且您应该能够使用堆栈跟踪来确定从该点开始发生的事情。

此外,如果您使用 FullDebugMode,泄漏检查通常会变得非常容易。您需要从 SourceForge 下载完整版的 FastMM4,并在启用 FullDebugMode 和日志记录的情况下重建您的项目。然后,您将获得一个文件,其中包含有关内存泄漏的详细调试信息,包括创建时的堆栈跟踪,而不仅仅是内存泄漏对话框。

关于multithreading - 来自线程的同步事件 - 内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16907076/

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