Утечка памяти на элементах управления Delphi

Я обнаружил странную утечку памяти в проекте, которому я был недавно назначен.

После завершения программа отображает следующее сообщение об ошибке FastMM4.

Ошибка FastMM4

В проекте используется BusinessSkinForm

TbsaSpeedButtonSubClass от третьей стороны BusinessSkinForm библиотеки, однако кнопки скорости в этой форме выглядят как обычные элементы управления формой VCL.

Когда я добавляю еще одну кнопку скорости в форму,

SpeedButton

У меня сейчас 25 экземпляров TbsaSpeedButtonSubClass эта утечка вместо 24.

Что заставляет меня думать, что утечка связана с TSpeedButton, Однако это кажется мне странным, поскольку я ожидаю, что компоненты формы будут автоматически освобождены формой при уничтожении.

возможно BusinessSkinForm делает что-то необычное с формой, что приводит к утечке...

Я не уверен, как избавиться от этой утечки

РЕДАКТИРОВАТЬ

Благодаря KenWhite у меня есть отчет об утечке памяти от FastMM4

Вот это на Pastebin

РЕДАКТИРОВАТЬ

Как показано в трассировке стека, проблема может быть прослежена до 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 ответ

Решение

Из того, что я вижу здесь, есть несколько способов, которыми я могу следовать отсюда.

  1. Отправить исправление в BusinessSkinForm для обработки кнопки скорости

  2. Жить с помощью работы вокруг, то есть: BSA.AdapterType := bsaUseNames; вместо BSA.AdapterType := bsaUseClasses;

  3. Заменить кнопки скорости на штатные TButton,

Другие вопросы по тегам