Утечка памяти на элементах управления Delphi
Я обнаружил странную утечку памяти в проекте, которому я был недавно назначен.
После завершения программа отображает следующее сообщение об ошибке FastMM4.
В проекте используется BusinessSkinForm
TbsaSpeedButtonSubClass
от третьей стороны BusinessSkinForm
библиотеки, однако кнопки скорости в этой форме выглядят как обычные элементы управления формой VCL.
Когда я добавляю еще одну кнопку скорости в форму,
У меня сейчас 25 экземпляров TbsaSpeedButtonSubClass
эта утечка вместо 24.
Что заставляет меня думать, что утечка связана с TSpeedButton
, Однако это кажется мне странным, поскольку я ожидаю, что компоненты формы будут автоматически освобождены формой при уничтожении.
возможно BusinessSkinForm
делает что-то необычное с формой, что приводит к утечке...
Я не уверен, как избавиться от этой утечки
РЕДАКТИРОВАТЬ
Благодаря KenWhite у меня есть отчет об утечке памяти от FastMM4
РЕДАКТИРОВАТЬ
Как показано в трассировке стека, проблема может быть прослежена до TMUSICMainForm.SkinForm_OnCreate(SkinForm: TForm);
Проблема, похоже, связана с BSA: TbsaSkinAdapter
Если я закомментирую строку BSA.ChangeSkinData;
утечки больше нет.
РЕДАКТИРОВАТЬ
Вот важная часть трассировки стека
--------------------------------2015/11/24 12:16:03-------------------------------- Блок памяти просочился. Размер: 308
Этот блок был выделен потоком 0x1258, и трассировка стека (адреса возврата) в то время была: 402AB6 [madZip][madZip][@GetMem] 4035F9 [madCrypt][madCrypt][TObject.NewInstance] 4039CA [madCrypt][madCrypt][@ClassCreate] 67438A [bsaadapter.pas][bsaadapter][TbsaSpeedButtonSubclass.Create][11537] 66137E [bsaadapter.pas][bsaadapter][TbsaHook.SetControl][265] 403Crypt] [2637] 403AptE [E] 665BFB [bsaadapter.pas][bsaadapter][TbsaSkinManager.DoControlMessage][4898] 6615B7 [bsaadapter.pas][bsaadapter][TbsaHookCollection.AddControl][2760] 404ACB [madExpStaEbceptE] ][bsaadapter][TbsaSkinManager.CollectSpeedButton][3544] 92C81D [Sources\uMainForm.pas][uMainForm][TMUSICMainForm.SkinForm_OnCreate][4778]
Блок в настоящее время используется для объекта класса: TbsaSpeedButtonSubclass
Номер присвоения: 475863
Текущий дамп памяти 256 байтов, начиная с адреса указателя 7E8A7670: 64 C9 65 00 00 00 00 00 00 00 00 00 00 00 00 00 68 F3 48 00 50 96 97 7E B8 5E 74 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 B8 D1 74 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 d E e.,,,,,,,,,,,, ч - н. P - - ~ ¸ ^ t ~ .,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, T т т ~.,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
РЕДАКТИРОВАТЬ
Мне удалось создать минимальный рабочий пример утечки памяти.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
BusinessSkinForm, bsaadapter, Buttons
;
type
TForm1 = class(TForm)
SpeedButton1: TSpeedButton;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
var
BSF: TbsBusinessSkinForm;
BSA: TbsaSkinAdapter;
begin
BSF := TbsBusinessSkinForm.Create(Self);
BSF.BorderIcons:=[biMinimize,biMaximize];
BSA := TbsaSkinAdapter.Create(Self);
BSA.AdapterType := bsaUseClasses;
BSA.ChangeSkinData;
end;
end.
Я обнаружил, что даже если я закомментирую, казалось бы, невинно выглядящие строки, как BSF.BorderIcons:=[biMinimize,biMaximize];
или же BSA.AdapterType := bsaUseClasses;
тогда утечка памяти исчезает.
Обратите внимание, что моя форма delphi в этом примере содержит 1 TSpeedButton
РЕДАКТИРОВАТЬ
Я должен также добавить, что я использую Windows 7 (64-разрядная версия), 6 ГБ оперативной памяти, Delphi 5, Business Skin версия 4.70
РЕДАКТИРОВАТЬ
bsaadapter
Блок в BusinessSkinForm содержит функцию
procedure TbsaSkinManager.DoUnhook(Control: TControl; Handle: HWnd);
var
i: integer;
SC: TbsaSubclass;
R: TRect;
begin
if FUnhooking then Exit;
if FUnhookedList = nil then
begin
FUnhooking := true;
Exit;
end;
FUnhooking := true;
try
for i := FHandleList.Count - 1 downto 0 do
begin
SC := TbsaSubclass(FHandleList[i]);
if (Handle <> 0) and (SC.Handle = Handle) then
begin
R := Rect(0, 0, 2000, 2000);
PostMessage(Handle, WM_NCPAINT, 0, 0);
InvalidateRect(Handle, @R, false);
FHandleList.Delete(i);
SC.Free;
end;
if (Control <> nil) and (SC.Control = Control) then
begin
FHandleList.Delete(i);
SC.FControl := nil;
if not (Control is TGraphicControl) then
SC.Free;
end;
end;
finally
FUnhooking := false;
end;
end;
Кажется, что кнопки скорости не освобождаются, потому что они являются экземплярами TGraphicControl
если нет (элемент управления TGraphicControl), то SC.Free;
Пока обычный TButton
будет освобожден
1 ответ
Из того, что я вижу здесь, есть несколько способов, которыми я могу следовать отсюда.
Отправить исправление в BusinessSkinForm для обработки кнопки скорости
Жить с помощью работы вокруг, то есть:
BSA.AdapterType := bsaUseNames;
вместоBSA.AdapterType := bsaUseClasses;
Заменить кнопки скорости на штатные
TButton
,