Lazarus

Programming => Graphics and Multimedia => Graphics => Topic started by: kveroneau on February 12, 2018, 02:02:32 am

Title: TImageList and memory leaks...
Post by: kveroneau on February 12, 2018, 02:02:32 am
I find it extremely easy to leak memory when using images placed inside a TImageList LCL control through the GUI in code, or the other way around.  I am having a slight feeling that I may not be using TImageList correctly as a result, so I am posting here to potentially get some guidance.  Or... perhaps anyone using TImageList doesn't check for leaks...  In modern OSes, do memory leaks matter as much, as the OS usually frees the memory the program allocated upon termination, or am I incorrect on how smart a modern OS memory manager really is...  Anyways, here are some examples of what I am trying to do, and I cannot seem to get rid of the leaks they create regardless if I try freeing the classes and such in the Form's onDestory event.

Code: Pascal  [Select][+][-]
  1. ImageList.GetIcon(0, Icon);
  2.  
This code allows me to reuse an icon in an ImageList for the Form's window, however upon closing the program a memory leak is found.  :o  How can I free this icon, or should I save the previous icon and restore that upon closing the form?

Code: Pascal  [Select][+][-]
  1. MenuItem.ImageIndex:=ImageList.AddIcon(ImagePreview.Picture.Icon);
  2.  
This works, but also causes a memory leak, so I tried to remedy that leak by attempting to do this:
Code: Pascal  [Select][+][-]
  1. var
  2.   img: TIcon;
  3. begin
  4.   img:=TIcon.Create;
  5.   img.SetSize(16,16);
  6.   img.Canvas.Draw(0,0,ImagePreview.Picture.Graphic);
  7.   MenuItem.ImageIndex:=ImageList.AddIcon(img);
  8. end;
  9.  
This code doesn't even work, although I believe I am copying the image correctly over to a new Canvas.  This causes a memory leak, but if I add a img.Free; to the end, the leak no longer exists, but the code still doesn't work.  The version that does work seen above causes a memory leak...  Also, looking deeper into TIcon, it appears to be a container for multiple icons, so it seems like it needs to be loaded from a Disk file in order to function, and cannot be used this way.  I did try this code originally with a TPicture with similar results.

This last one I thought would work, as how else does one load external images into a TImageList, or are we expected to load a TImageList using the Lazarus GUI, and then not add new images, or use the images with TImageList.GetIcon() call?

My question here is, how do you add icons to a TImageList using code without resulting in a memory leak, or should I just not care about memory leaks on protected mode operating systems?  My next test will be to load a PNG from disk and add that to a TImageList and see what the results are.
Title: Re: TImageList and memory leaks...
Post by: wp on February 12, 2018, 09:13:27 am
The imagelist stores copies of the images added. Therefore, you must destroy the images after adding. The following code works for me correctly, without a memory leak:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   ico: TIcon;
  4. begin
  5.   ico := TIcon.Create;
  6.   try
  7.     ico.LoadFromFile('C:\lazarus-trunk_fpc304\images\icons\aqua.ico');
  8.     ToolButton1.ImageIndex := ImageList1.AddIcon(ico);
  9.   finally
  10.     ico.Free;   // <---- missing in your code
  11.   end;
  12. end;
TinyPortal © 2005-2018