Reputation: 199
Background: Windows 64-bit application, Firemonkey, Delphi XE7
I have about 10 TStringGrid components and all of which are using the same onDrawColumnCell to change cell colors when the Value in the cells is not 'Normal.'
I am using the following code, but the severe memory leaks happens if the red cells are displayed on the screen.(if I roll the page away where no red cell is shown, no memory is leaked).
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;
Does anyone know how to solve the memory leak problem?
Thanks
Upvotes: 0
Views: 729
Reputation: 612993
You are leaking RowColor
. Like any resource that is managed by you, you need to destroy it. Usee the standard pattern:
Obj := TMyClass.Create;
try
// do stuff with Obj
finally
Obj.Free;
end;
Obviously in you code you replace Obj
with RowColor
. I wrote the code with generic names to try to bring out the fact that this is a pattern. Apply this pattern whenever you have an object whose lifetime you have to manage, and whose lifetime does not extend beyond the function in which it is created.
If you were using one of the mobile compilers then your code would be fine. The mobile compilers use ARC, automatic reference counting to manage the lifetime of class instances. But that's not the case with the desktop compilers.
If you installed the full version of FastMM you could get it to give you stack traces for the allocations that led to any leaks. That is usually enough to let you work out the cause of the leak.
FWIW I'd code it more like this, only creating the brush if needed:
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;
Upvotes: 1