【问题标题】:Memory Leak on TStringGrid's onDrawColumnCell eventTStringGrid 的 onDrawColumnCell 事件上的内存泄漏
【发布时间】:2015-03-06 06:43:48
【问题描述】:

背景: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; 

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

谢谢

【问题讨论】:

  • 您何时发布TBrush 实例?

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


【解决方案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; 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-27
    相关资源
    最近更新 更多