内存泄漏TStringGrid的onDrawColumnCell事件

时间:2015-03-06 06:43:48

标签: delphi memory-leaks firemonkey delphi-xe7 tstringgrid

后台:Windows 64位应用程序,Firemonkey,Delphi XE7

我有大约10个TStringGrid组件,并且当单元格中的值不是“正常”时,所有这些组件都使用相同的onDrawColumnCell来更改单元格颜色。

我正在使用以下代码,但如果屏幕上显示红色单元格,则会发生严重的内存泄漏。(如果我将页面滚动到没有显示红色单元格的位置,则没有内存泄漏)。

procedure TForm.grid_DrawColumnCell(Sender: TObject;
  const Canvas: TCanvas; const Column: TColumn; const Bounds: TRectF;
  const Row: integer; const Value: TValue; const State: TGridDrawStates);
var
  RowColor: TBrush;
begin

  RowColor := TBrush.Create(TBrushKind.Solid, TAlphacolors.Alpha);

  if (Value <> 'Normal') then
    RowColor.Color := TAlphacolors.Red
  else
    RowColor.Color := TAlphacolors.Null;

  Canvas.FillRect(Bounds, 0, 0, [], 1, RowColor);

  { perform default drawing }
  TGrid(Sender).DefaultDrawColumnCell(Canvas, Column, Bounds, Row,
    Value, State);
end; 

有谁知道如何解决内存泄漏问题?

由于

1 个答案:

答案 0 :(得分:1)

您正在泄露RowColor。与您管理的任何资源一样,您需要销毁它。使用标准模式:

Obj := TMyClass.Create;
try
  // do stuff with Obj
finally
  Obj.Free;
end;

显然,在您的代码中,您将Obj替换为RowColor。我用通用名称编写了代码,试图说明这是一个模式。只要有一个必须管理其生命周期的对象,并且其生命周期不超出创建它的函数,就应用此模式。

如果您使用的是其中一个移动编译器,那么您的代码就可以了。移动编译器使用ARC,自动引用计数来管理类实例的生命周期。但桌面编译器的情况并非如此。

如果您安装了FastMM的完整版本,您可以使用它来为分配导致任何泄漏的堆栈跟踪。这通常足以让你找出泄漏的原因。

FWIW我更喜欢这样编码,只在需要时创建画笔:

var
  RowColor: TBrush;
begin
  if Value <> 'Normal' then
  begin
    RowColor := TBrush.Create(TBrushKind.Solid, TAlphacolors.Red);
    try
      Canvas.FillRect(Bounds, 0, 0, [], 1, RowColor);
    finally
      RowColor.Free;
    end;
  end;
  TGrid(Sender).DefaultDrawColumnCell(Canvas, Column, Bounds, Row,
    Value, State);
end;