Я пытаюсь найти источник утечки памяти из потока. Поток запускает синхронизированные события повторно, возвращая объект, защищенный потоком.Синхронизированное событие из потока - утечка памяти
я вызвать это событие в потоке путем вызова процедуры ...
procedure TDeskMonThread.DoOnImage(const ID: Integer; const R: TRect;
ABmp: TLockBmp);
begin
FSyncOnImageID:= ID;
FSyncOnImageRect:= R;
FSyncOnImageBmp:= ABmp;
Synchronize(SYNC_OnImage);
end;
3 частных полей используются только для этой цели - временного хранения для использования в триггера событий. 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;
Память это то, что меня смущает:
x 3
варьируется в зависимости от того, как долго он был запущен, но не число итераций. Например, поток может повторить 20 итераций и показать x 3
или повторить 10 итераций и показать x 7
, но я не могу даже найти шаблон количества утечек по сравнению с тем, сколько итераций. Кажется, это происходит в случайные моменты, а не на каждой итерации.
Итак, я пошел на отладку процедуры ResizeBitmap
, но когда я запускаю ее сам, даже многократно и быстро, я никогда не получаю утечек памяти. Кажется, что это связано с многократным вызовом его из потока. Я знаю, что это создает/уничтожает экземпляр TBitmap
, который, возможно, не самый лучший способ, но все же я получаю эту утечку памяти, когда она многократно вызывается из потока. Я предполагаю, что есть скрытое исключение (из ресурсов), которое никогда не вызывает исключения, и, таким образом, попадает в ловушку как утечка памяти.
Откуда могла произойти утечка памяти? Как я могу это предотвратить?
Обратите внимание, что разблокировка растрового изображения ничего не делает, чтобы поток продолжал выполнять какую-либо работу. В потоке по-прежнему нужно ожидать возврата «Синхронизация», что не произойдет, пока обработчик события не закончит работу. –
Вам нужна полная версия FastMM для получения трассировки стека распределения.Или даже лучше, обнаружение утечки на madExcept 4. –
@Rob Правда, я действительно имел в виду, что он не остается заблокированным слишком долго - как только я его больше не буду нуждаюсь в нем, откройте его, чтобы что-то еще могло получить к нему (поскольку следующие две строки кода могут занимать немного времени). Это предполагает, однако, что есть еще больше потоков, которых нет, но для будущей реализации большего количества потоков я уверен, что он будет готов, если я намереваюсь это сделать. –