Heaptrc and MacOS lazarus / 12-Debugger ---------------------------------------------------------------------- ahnz · 2019-05-01 20:49 Heres what I have OS: OSX High Sierra 10.13.6 Lazarus: 2.0.2 rev.61074 Widgetset: Cocoa Target: 64bit OSX Compiler: FPC 3.0.4 [2017/11/26] for x86_64 Debug: LLDB  (with fpdebug)(Beta) Path: /usr/bin/lldb Version: lldb-1000.11.38.2 I'm trying to use heaptrc on my application to identify memory leaks. I've done what heaptrc and leak view wiki pages says .. QuoteTo enable this in your Lazarus project: go to Project Options/Linking and in the Debugging section enable Use Heaptrc unit (check for mem-leaks) (-gh) To get meaningful heaptrc results with descriptions to your code lines and not just assembler addresses, go to Tools/Options/Debugger/general and set a debugger. ... but I'm not getting any meaningful descriptions of the code lines, just the assembler addresses ... The trace file , truncated for the sake of brevity... QuoteHeap dump by heaptrc unit 1578 memory blocks allocated : 2098562/2101984 1577 memory blocks freed     : 2098442/2101864 1 unfreed memory blocks : 120 True heap size : 950272 (96 used in System startup) True free heap : 949888 Should be : 949928 Call trace for block $0000000100B59500 size 120 study:Contents andy$ cat ~/Desktop/memleak.trc /mnt/NAS/Documents/Andy/Pascal/src/MemLeak/project1.app/Contents/MacOS /project1 Heap dump by heaptrc unit 1278 memory blocks allocated : 2085956/2088320 1265 memory blocks freed     : 2085293/2087592 13 unfreed memory blocks : 663 True heap size : 1015808 (96 used in System startup) True free heap : 1012896 Should be : 1013320 Call trace for block $0000000105991680 size 27 Call trace for block $00000001059915C0 size 26 ... Call trace for block $00000001059885A0 size 256   $0000000100152168   $0000000100152072   $0000000100151EBB   $0000000100149FE1   $000000010002FA66   $000000010002F90B   $00000001000329D5 ... My basic program to reproduce the problem. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program project1; {$mode objfpc}{$H+} uses {$IFDEF UNIX} {$IFDEF UseCThreads}  cthreads, {$ENDIF} {$ENDIF}  Interfaces, // this includes the LCL widgetset  Forms,  Classes,  Unit1,  OSUtils,  SysUtils { you can add units after this }; {$R *.res}  var  htrc: string;  i: integer;  leaky: TStringList; begin   htrc := GetUserDir + '/Desktop/memleak.trc';  if FileExists(htrc) then    DeleteFile(htrc);  SetHeapTraceOutput(htrc);   RequireDerivedFormResource := True;  Application.Scaled := True;  Application.Initialize;  Application.CreateForm(TForm1, Form1);   leaky := TStringList.Create;  for i := 0 to 10 do    leaky.Add(IntToStr(i));   Application.Run;end. The button on th form simply calls Close to terminate the program. Can anyone throw any light on what I might be missing, doing wrong or should try? Cheers ---------------------------------------------------------------------- Martin_fr · 2019-05-01 21:42 See https://bugs.freepascal.org/view.php?id=32775 ---------------------------------------------------------------------- ahnz · 2019-05-01 22:58 Thanks ---------------------------------------------------------------------- Martin_fr · 2019-05-02 01:12 There may be another option. But it requires svn trunk (and will not be merged to fixes) I have not tested it on Mac yet, but it should be ok. In the View menu is an entry "Leaks and traces" (should be there, if not install package LeakView) You can paste your leak there. You paste the data that only has addresses, and misses the lines/filenames. It has a "Resolve" button. Since revision 61105 this uses FpDebug (before that it used the fpc code, that does not support cocoa). FpDebug has support for 64 bit cocoa. The resolve button opens a file dialog. Select the app, that produced the leak (Probably need to select the bundle, but if that doesnt work then select the exe in Contents/MacOS). The app must be compiled with debug info, otherwise it will not work. The leak view should now look up each address, and resolve it. I do hope it works.... ---------------------------------------------------------------------- ahnz · 2019-05-02 11:05 Thanks. I'm still trying to get my head around svn. currently I have 61074M according to Help|About. If I want to get 61105, do I just do an "svn update" ??? ---------------------------------------------------------------------- Martin_fr · 2019-05-02 11:30 The "M" at the end means you have local modifications. You can do an   svn info to see the current svn url. It be something like   https://svn.freepascal.org/svn/fpc/........ either branches/fixes...   (or tag...) or trunk If it not trunk, you can do   svn switch https://svn.freepascal.org/svn/fpc/trunk or   svn switch ^/trunk I use a frontend on windows, so I had to look up the syntax myself. If you want to keep fixes, and have trunk, then check it out into a new folder   svn checkout https://svn.freepascal.org/svn/fpc/trunk folder_for_trunk After the switch, you should already be up to date, but you can do "svn up"   svn log | head - n 20 should show you the log entries for the last revisions. Depending how many new revisions were added since, you may see 61105 in the list. (While you are on fixes branch, svn log will not show this) ---------------------------------------------------------------------- ahnz · 2019-05-02 20:46 Hi, When you say Quote from: Martin_fr on May 02, 2019, 03:12:09 am... it requires svn trunk (and will not be merged to fixes) With my limited knowledge of svn, I thought branches (fixes) were merged into trunk, not trunk into fixes but your comment suggest otherwise. Does this mean if I take trunk, that I can't benefit from fixes on that trunk? Anyway, I've done this... Quotecd /Developer/lazarus/ svn info svn switch ^/trunk svn up Updating '.': Skipped 'lcl' -- Node remains in conflict Skipped 'components' -- Node remains in conflict Skipped 'ide' -- Node remains in conflict At revision 61108. Summary of conflicts:   Skipped paths: 3 Rebuilt and now Help|About shows 61074:61108MS I've done a Clean & Rebuild of my application, run with debug Ok. But when I try the Resolve" as you suggest (a) using the executable, nothing appears to happen (b) using the app bundle, I get an "Out of Memory" error For what its worth, I've attached a Laz debug log for (b). I won't upload both, they're too big. Cheers ---------------------------------------------------------------------- Martin_fr · 2019-05-02 21:08 QuoteSkipped 'lcl' -- Node remains in conflict do an svn -R revert . svn up . If you still get an error on any folder, then delete that folder, e.g.: rm -rf lcl svn up . will restore the folder. If you made any changes to the Lazarus sources that you want to keep: Save them before, and re-apply after. ---------------------------------------------------------------------- ahnz · 2019-05-02 21:42 Cool. so now I have 2.0.3 61008S according to Help|About. I still get the same results when trying to "Resolve". this time though I used the basic program I mentioned at the start rather than the main app I'm writing so the logs are much smaller All attached Cheers ---------------------------------------------------------------------- Martin_fr · 2019-05-02 22:10 I'll look into it.... In a bit. ---------------------------------------------------------------------- Martin_fr · 2019-05-03 18:47 Ok, I just did a test run. It worked for me. Lazarus build 64bit for cocoa Project with leak, build 64bit for cocoa Project is a new application, empty form, with an FormCreate event:   TObject.Create; So that leaks one TObject. I copied the trace, and resolved it. No errors, and unit-names/lines were added. I used the app bundle for the resolve button. Just one note: The trace begins in customform, which is the caller of FormCreate. So effectively it lacks the top line. This can happen, if the leaking code that was called is optimized by fpc. If that happens, it can not be helped. At least not if the code (like TObject.Create (or actually TObject.NewInstance)) is in the rtl (or fpc packages. Unless you like to build your own fpc. Please check in the file  components\leakview\leakinfo.pas Around line 870 There should be a nested     procedure LoadDwarf; If not, then your "svn switch" did not work. The output of "svn info" should also tell that. If you have that LoadDwarf in that file, see if you can test with an empty form, the way I did. Also if you have the LoadDwarf, then try running the IDE in lldb, get the out of mem, and do a "bt" in lldb. ---------------------------------------------------------------------- Martin_fr · 2019-05-05 18:14 Quote from: ahnz on May 02, 2019, 11:42:03 pmCool. so now I have 2.0.3 61008S according to Help|About. 2.0.3 is still fixes. Trunk is 2.1 (or 2.1.0) that means the svn switch did not work. ---------------------------------------------------------------------- ahnz · 2019-05-05 20:54 Thanks, I've tried a few things to get to 2.1. The last, and my current state, is a fresh install of 2.0.2, followed by Quotesvn co https://svn.freepascal.org/svn/fpc/trunk . svn update make bigide LCL_PLATFORM=carbon CPU_TARGET=i386 study:lazarus andy$ svn info Path: . Working Copy Root Path: /Developer/lazarus URL: https://svn.freepascal.org/svn/fpc/trunk Relative URL: ^/trunk Repository Root: https://svn.freepascal.org/svn/fpc Repository UUID: 3ad0048d-3df7-0310-abae-a5850022a9f2 Revision: 42002 Node Kind: directory Schedule: normal Last Changed Author: pierre Last Changed Rev: 41983 Last Changed Date: 2019-05-05 00:45:02 +1200 (Sun, 05 May 2019) and now it showing 2.0.2 r42002M  and still now no sign of this Quote from: Martin_fr on May 03, 2019, 08:47:57 pm Please check in the file  components\leakview\leakinfo.pas Around line 870 There should be a nested     procedure LoadDwarf; I've tried this twice What have I done wrong? Cheers ---------------------------------------------------------------------- ahnz · 2019-05-05 21:35 I realised where I might have gone with my earlier attempts... point at svn/fpc rather than fpc/lazarus. So I did a fresh 2.0.2 install, followed by Quotesvn co https://svn.freepascal.org/svn/lazarus/trunk make bigide LCL_PLATFORM=carbon CPU_TARGET=i386 study:lazarus andy$ svn info Path: . Working Copy Root Path: /Developer/lazarus URL: https://svn.freepascal.org/svn/lazarus/trunk Relative URL: ^/trunk Repository Root: https://svn.freepascal.org/svn/lazarus Repository UUID: 4005530d-fff6-0310-9dd1-cebe43e6787f Revision: 61162 Node Kind: directory Schedule: normal Last Changed Author: dmitry Last Changed Rev: 61162 Last Changed Date: 2019-05-06 08:42:10 +1200 (Mon, 06 May 2019) and now its showing 2.0.2 r61162M, still no sign of 2.1 or any nested procedure LoadDwarf around line 870 of components\leakview\leakinfo.pas ---------------------------------------------------------------------- Martin_fr · 2019-05-05 21:39 Argh, now I see it. My fault... Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i svn co https://svn.freepascal.org/svn/fpc/trunk . When I copied that I must have been in the wrong folder. That is the url to get the svn version of freepascal. You neither need nor want that.... Sorry. what you want is https://svn.freepascal.org/svn/lazarus/trunk Create a new empty folder: Code: [Select]mkdir lazarus_2_1 cd lazarus_2_1 svn co https://svn.freepascal.org/svn/lazarus/trunk . make bigide LCL_PLATFORM=carbon CPU_TARGET=i386 The make will take a while. At the end you should have a lazarus file in that folder. And be able to start the app bundle that is in the folder. also in that folder create a file lazarus.cfg with the content --primary-config-path=/home/wherever/path The path to an empty folder, where you want the config to go. ---------------------------------------------------------------------- Martin_fr · 2019-05-05 21:41 Ups, overlapped replies. The svn info says you should have the right data. You did that in a new empty folder? Can you start from console lazarus.app/Contents/MacOS/lazarus ? In that folder Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i grep -i LoadDwarf components\leakview\leakinfo.pas ---------------------------------------------------------------------- VTwin · 2019-05-05 21:42 Martin_fr is much more informed than I, and has steered you in the correct direction. I am running Cocoa trunk, currently at 2.1.0 61159M using svn up, so might be able to help. The fixes branch is always behind the trunk, and I have resorted to trunk to get the latest Cocoa fixes. ---------------------------------------------------------------------- ahnz · 2019-05-05 23:04 Quote from: VTwin on May 05, 2019, 11:42:48 pmMartin_fr is much more informed than I, and has steered you in the correct direction. I am running Cocoa trunk, currently at 2.1.0 61159M using svn up, so might be able to help. The fixes branch is always behind the trunk, and I have resorted to trunk to get the latest Cocoa fixes. Thanks, but I don't seem to be having too much luck getting 2.1.0 r61162 running (see next post) ---------------------------------------------------------------------- ahnz · 2019-05-05 23:24 Quote from: Martin_fr on May 05, 2019, 11:41:42 pmUps, overlapped replies. No problem. I started redoing the install as you were replying What I've done... Completely deleted the Lazarus install then ...  Quotesvn co https://svn.freepascal.org/svn/lazarus/trunk . make bigide LCL_PLATFORM=carbon CPU_TARGET=i386 Though it completed without errors, I did get a bunch of warnings like this .. Quoteld: warning: text-based stub file /System/Library/Frameworks//Foundation.framework/Foundation.tbd and library file /System/Library/Frameworks//Foundation.framework/Foundation are out of sync. Falling back to library file for linking. I created a basic project as you suggested .. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program project1; {$mode objfpc}{$H+} uses  {$IFDEF UNIX}{$IFDEF UseCThreads}  cthreads,  {$ENDIF}{$ENDIF}  Interfaces, // this includes the LCL widgetset  Forms, Unit1  { you can add units after this }; {$R *.res} begin  RequireDerivedFormResource:=True;  Application.Scaled:=True;  Application.Initialize;  Application.CreateForm(TForm1, Form1);  Application.Run;end.   unit Unit1; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, Forms, Controls, Graphics, Dialogs; type   { TForm1 }   TForm1 = class(TForm)    procedure FormCreate(Sender: TObject);  private   public   end; var  Form1: TForm1; implementation {$R *.lfm} { TForm1 } procedure TForm1.FormCreate(Sender: TObject);begin    TObject.Create;end; end. But the build "errored"  with a bunch of these .. QuoteError: ld: warning: text-based stub file /System/Library/Frameworks//OpenGL.framework/OpenGL.tbd and library file /System/Library/Frameworks//OpenGL.framework/OpenGL are out of sync. Falling back to library file for linking. That said, it does run!, but with no trc file that I can find. So I added SetHeapTraceOutput ... Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     SetHeapTraceOutput('/Users/andy/Desktop/memleak.trc');  TObject.Create;   But the compile fails "unit1.pas(33,3) Error: Identifier not found "SetHeapTraceOutput" I thought SetHeapTraceOutput was part of the Heaptrc unit automatically included when building with -gh, which it is ... Quote/usr/local/bin/fpc -MObjFPC -Scaghi -CirotR -gw2 -gl -gh -gt -k-framework -kCocoa -l -vewnhibq -Filib/x86_64-darwin -Fu/Developer/lazarus/lcl/units/x86_64-darwin/cocoa -Fu/Developer/lazarus/lcl/units/x86_64-darwin -Fu/Developer/lazarus/components/lazutils/lib/x86_64-darwin -Fu/Developer/lazarus/packager/units/x86_64-darwin -Fu. -FUlib/x86_64-darwin -FE. -oproject1 -dLCL -dLCLcocoa Cheers ---------------------------------------------------------------------- Martin_fr · 2019-05-05 23:42 the best way to get the heaptrc output is to run your app with a console. Either use the option in the global debugger settings, to enable the debugger to launch a terminal. Or compile your app, then run it outside the IDE from a terminal, and the log goes to console. Or use the environment: https://www.freepascal.org/docs- html/rtl/heaptrc/environment.html (I haven't tried that last one, not for the logfile at least) ---------------------------------------------------------------------- ahnz · 2019-05-05 23:46 Thanks Martin_f, I was just playing around and about to reply when you posted. I've moved the SetHeapTraceOutput to the program file rather than the forms unit and things are looking a lot more as expected.. I'll have a play with the other options you suggest. Any idea what these are all  about ... Quoteld: warning: text-based stub file /System/Library/Frameworks//Foundation.framework/Foundation.tbd and library file /System/Library/Frameworks//Foundation.framework/Foundation are out of sync. Falling back to library file for linking. ---------------------------------------------------------------------- Martin_fr · 2019-05-05 23:48 You can google the ld warning. It seem to relate to apple tools... My guess: You did build for carbon   make bigide LCL_PLATFORM=carbon CPU_TARGET=i386 Maybe those are outdated? (on the  side of apple) The google responses give a lot of different tips, which all seem to work for some people and not for others With lazarus trunk, you also have all the latest cocoa fixes. So maybe make bigide LCL_PLATFORM=cocoa CPU_TARGET=x86_64 You can always create a 2nd folder for a 2nd lazarus (just make sure you do the lazarus.cfg for separate configs) ---------------------------------------------------------------------- ahnz · 2019-05-06 20:04 Quote from: Martin_fr on May 06, 2019, 01:48:59 amYou can google the ld warning. It seem to relate to apple tools... My guess: You did build for carbon   make bigide LCL_PLATFORM=carbon CPU_TARGET=i386 Maybe those are outdated? (on the  side of apple) The google responses give a lot of different tips, which all seem to work for some people and not for others With lazarus trunk, you also have all the latest cocoa fixes. So maybe make bigide LCL_PLATFORM=cocoa CPU_TARGET=x86_64 You can always create a 2nd folder for a 2nd lazarus (just make sure you do the lazarus.cfg for separate configs) Thanks. that gives me something to work on Cheers ---------------------------------------------------------------------- ahnz · 2019-05-07 01:08 I posted this over on another board, but the feedback seems to be that it shouldn't be a memory leak. https://forum.lazarus.freepascal.org/index.php/topic,45312.0.html Am I mis-using or mis-reading the heap trc output ---------------------------------------------------------------------- Martin_fr · 2019-05-07 11:46 Ah, it looks like you got the "resolve" function working ---------------------------------------------------------------------- VTwin · 2019-05-07 16:14 I install Cocoa trunk something like this: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i cd /Developermkdir laz_trunkcd laz_trunksvn checkout https://svn.freepascal.org/svn/lazarus/trunkmake clean all LCL_PLATFORM=cocoa CPU_TARGET=x86_64open lazarus.app --args "-- pcp=~/.laz_trunk"[/code] Then update like this: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i cd /Developer/laz_trunk svn updatemake clean all LCL_PLATFORM=cocoa CPU_TARGET=x86_64open lazarus.app --args "--pcp=~/.laz_trunk" You need follow that by installing the debugger package.  I am at 2.1.0 r61174M. ---------------------------------------------------------------------- Martin_fr · 2019-05-07 16:23 I think "make bigide ...." has the packages already installed. But now that you are done, that does not matter. you can put the --pcp=.... (without quotes) into a file called lazarus.cfg in the laz_trunk directory. But you need to replace the ~ by /home/.... This file is read line by line. Each line (if not starting with # for comment) is taken as one command line arg. (But no shell expansion for ~) You can verify the effect under menu: View > IDE internals > About IDE It shows the current used pcp. ---------------------------------------------------------------------- VTwin · 2019-05-07 16:32 Quote from: Martin_fr on May 07, 2019, 06:23:17 pmI think "make bigide ...." has the packages already installed. But now that you are done, that does not matter. you can put the --pcp=.... (without quotes) into a file called lazarus.cfg in the laz_trunk directory. But you need to replace the ~ by /home/.... This file is read line by line. Each line (if not starting with # for comment) is taken as one command line arg. (But no shell expansion for ~) You can verify the effect under menu: View > IDE internals > About IDE It shows the current used pcp. Many thanks for the tips. I'll check if the packages include "lazdebuggerfplldb.lpk". That would save me the extra compile. ---------------------------------------------------------------------- Martin_fr · 2019-05-07 17:08 Also once you have the IDE build, you can rebuild it from the Tools menu. (you may have to set the target cocoa/x86_64 ; not sure) Even after an svn up. ---------------------------------------------------------------------- ahnz · 2019-05-07 20:33 Quote from: Martin_fr on May 07, 2019, 01:46:55 pmAh, it looks like you got the "resolve" function working Did I not say .. apologies, my bad - Yes I got it working, many thanks to you. I managed to get x86_64 IDE up and running as well without any issues. But I'm still getting the same to problems QuoteError: ld: warning: text-based stub file /System/Library/Framewor ks/CoreServices.framework/Versions/A/Frameworks/AE.framework/Versions/ A/AE.tbd and library file /System/Library/Frameworks/CoreServices.fram ework/Versions/A/Frameworks/AE.framework/Versions/A/AE are out of sync. Falling back to library file for linking. This one I've decided to live with, at least for now. Its the heaptrc that I can't get a grip on. Things like this (another I've found since I posted my other thread on the subject) Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var  MyForm: TMatchedStampsForm;...begin   MyForm := TMatchedStampsForm.Create(Self);...  MyForm.ShowModal;  FreeAndNil(MyForm);                            ... .. and why the MyForm.ShowModal shows up in the attached heaptrc output. (its line 1775 in the src.). I've learned about the un- necessary use of FreeAndNil.. just haven't changed it yet ) ---------------------------------------------------------------------- Martin_fr · 2019-05-07 21:18 Well, it doesn't have to be a leak in your code. It could also be in the cocoa widgetset. Both possible. From the info avail, I would at first guess widgetset. Though that is not necessary true. Lets assume something is allocated during ShowModal. Maybe the memory for a string which is refcounted. Then at some point you create another object that references the string, or you do some pointer stuff "new(Pstring)^ := TheStringFromModal". You leak that other object or pointer. Then you also leak that string. Heaktrc does not realize that the string was leaked at that later time. HeapTrc only shows you where it was allocated. Of course for the above to happen you would expect that other object/pointer to be in the list of leaks. But now say, you have some code that writes to random memory (e.g. a dangling pointer). The data to which the pointer points no longer exists, so the pointer points to something else, that just happened to re-use that memory. Now say again ShowModal allocetad mem (that would be ok). It stores a pointer to that mem (eg to the object). Then Later show modal would free that object. But your code, writes nil to the dangling pointer. And that happens to be the same address as the above object. Then the modal code sees nil, and cannot free the object. Admitted, not a likely case. But a possibility. Leaks are tricky. FreeAndNil may not always be needed. It does no harm either. (I heard arguments saying it does, and it may on a first glance look like that, but the great balance may be different. So its a matter what math you subscribe too) If you do Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Procedure Bar;var Foo: TFoo;begin  Foo := getObject():  if Foo <> nil then begin     dosomething;    Foo.Destroy  end;end; You can use Destroy because: - You already ensured Foo <> nil - Foo goes out of scope on the next line.   The remaining dangling pointer can never be accessed. If you did not have "if Foo <> nil then begin" then you would maybe use   Foo.Free; because Foo maybe nil, and Free cares about that. But in both cases you can also do FreeAndNil. 1) It does not hurt (unless you need code so time critical you should write it in asm instead) 2) Always using FreeAndNil means you will not accidentally NOT use it in other places 3) Foo is now a local var. What if you refactor it to be a field on "self" or a global var? Then you have to remember to change to FreeAndNil. There is the argument that your code should be correct, and not even try to access the variable, if it is not assigned, or if the assigned object has been freed. And maybe that is how you designed it. But even then, bugs happen, and FreeAndNil may prevent them. If you want to catch them, then write your own function   FreeThenBadPointer and set the variable to pointer(-1). If your code accesses the var, where it should not, then it will crash and you know you got an error. In some case you want to use FreeThenNil. But that is a diff story. ---------------------------------------------------------------------- ahnz · 2019-05-08 21:19 Thankyou very much Martin for such a detailed and helpful response - certainly gives me some stuff to think about. I  have since done the following simple test... Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program project1; {$mode objfpc}{$H+} uses  {$IFDEF UNIX}{$IFDEF UseCThreads}  cthreads,  {$ENDIF}{$ENDIF}  Interfaces, // this includes the LCL widgetset  Forms, Unit1, Unit2  { you can add units after this }; {$R *.res} begin  SetHeapTraceOutput('/Users/andy/Desktop/memleak.trc');  RequireDerivedFormResource:=True;  Application.Scaled:=True;  Application.Initialize;  Application.CreateForm(TForm1, Form1);  Application.CreateForm(TForm2, Form2);  Application.Run;end.      unit Unit1; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, OSUtils, Unit2; type   { TForm1 }   TForm1 = class(TForm)    Button1: TButton;    procedure Button1Click(Sender: TObject);  private   public   end; var  Form1: TForm1; implementation {$R *.lfm} { TForm1 } procedure TForm1.Button1Click(Sender: TObject);begin  if Form2.ShowModal = mrOk then  Close;end; end.  unit Unit2; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls; type   { TForm2 }   TForm2 = class(TForm)    Button1: TButton;    Button2: TButton;    procedure Button1Click(Sender: TObject);    procedure Button2Click(Sender: TObject);  private   public   end; var  Form2: TForm2; implementation {$R *.lfm} { TForm2 } procedure TForm2.Button1Click(Sender: TObject);begin  ModalResult := mrOk;end; procedure TForm2.Button2Click(Sender: TObject);begin  ModalResult := mrCancel;end; end. ... and heaptrc shows (suggests) a memory leak at "if Form2.ShowModal = mrOk then" ... so I'm reckoning your first guess that its the widgets isn't too far off the mark Thanks again for all the assistance