Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2017-06

Is this a bug?

14 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Wolf

The following program produces these two memory leaks:

Heap dump by heaptrc unit
2 memory blocks allocated : 188/208
0 memory blocks freed : 134/144
2 unfreed memory blocks : 54
True heap size : 32768
True free heap : 32320
Should be : 32448
Call trace for block $00007FFFF7FF31A0 size 27
Call trace for block $00007FFFF7FF30C0 size 27

If the call to "halt;" is commented out, there is no memory leak reported. Is this intentional?

program TestBed;
begin
   {run the program with this run parameter: FileToLoad -v -t -r=0.0001}
   write(ParamCount,'  ');
   write(Sizeof(ParamStr(0)),'  ');
   write(Length(ParamStr(0)),'  ');
   writeln(ParamStr(0));
   write(Sizeof(ParamStr(1)),'  ');
   write(Length(ParamStr(1)),'  ');
   writeln(ParamStr(1));
   write(Sizeof(ParamStr(2)),'  ');
   write(Length(ParamStr(2)),'  ');
   writeln(ParamStr(2));
   write(Sizeof(ParamStr(3)),'  ');
   write(Length(ParamStr(3)),'  ');
   writeln(ParamStr(3));
  halt;     // terminating with "halt" causes memory leaks
  end.      // no memory leak

The size of the unfreed memory blocks varies, if the one or the other of the program blocks are commented out. There is no discernible correlation (to me, at least) between them and the data they are supposed to store. Also, the total number of memory blocks allocated and later freed varies, the record observed so far is 11 blocks allocated. This apparently varies whenever my system is rebooted, and appears to have something to do with what else I am running / have been running.

System: Kubuntu 16.4, Lazarus 1.6+dfsg-1 dated 2016-03-01, FPC 3.0.0

wolf

Reply by email

Ondrej Pokorny
to Wolf
Wolf wrote
If the call to "halt;" is commented out, there is no memory leak reported. Is this intentional?

Yes, halt kills the program without finalizing anything. No code is executed afterwards. Everything that is allocated at the time Halt is executed results in a memory leak.

Ondrej

Reply by email

Mattias Gaertner
to Wolf: The following program produces these two memory leaks: Heap dump by heaptrc unit 2 memory…
Show quoted text 14 lines
The following program produces these two memory leaks: Heap dump by heaptrc unit 2 memory blocks allocated : 188/208 0 memory blocks freed : 134/144 2 unfreed memory blocks : 54 True heap size : 32768 True free heap : 32320 Should be : 32448 Call trace for block $00007FFFF7FF31A0 size 27 Call trace for block $00007FFFF7FF30C0 size 27 If the call to "halt;" is commented out, there is no memory leak reported. Is this intentional?

Yes.
"Halt" immediately jump to the finalization sections. That means any try..finally sections are skipped, including the implicit frees for the temporary strings of your example.

Mattias

Reply by email

Mattias Gaertner
to Ondrej Pokorny: Yes, halt kills the program without finalizing anything. No code is executed afterwards.…
Show quoted text 7 lines
On 16.06.2017 9:12, Wolf via Lazarus wrote: > If the call to "halt;" is commented out, there is no memory leak > reported. Is this intentional? Yes, halt kills the program without finalizing anything. No code is executed afterwards. Everything that is allocated at the time Halt is executed results in a memory leak.

Halt calls the finalization sections.

Mattias

Reply by email

Ondrej Pokorny
to Mattias Gaertner
Mattias Gaertner wrote 10 lines
On Fri, 16 Jun 2017 09:25:24 +0200 Ondrej Pokorny via Lazarus wrote: > On 16.06.2017 9:12, Wolf via Lazarus wrote: >> If the call to "halt;" is commented out, there is no memory leak >> reported. Is this intentional? > Yes, halt kills the program without finalizing anything. No code is > executed afterwards. Everything that is allocated at the time Halt is > executed results in a memory leak. Halt calls the finalization sections.

Uppps. Thanks for the correction.

Ondrej

Reply by email

Wolf
to Mattias Gaertner: On Fri, 16 Jun 2017 09:25:24 +0200 Halt calls the finalization sections. Mattias

Now I am nicely confused: If halt does call finalization sections, isn't then all heap space requested by the system unit supposed to be freed as well? I do have observed at times that some, and sometimes even all heap space requested by the system unit, does get freed when calling halt. So, what does this program show? Expected behavior that should not be changed, or is it unexpected behavior that ought to be reported and changed? wolf

Mattias Gaertner wrote 12 lines
On Fri, 16 Jun 2017 09:25:24 +0200 Ondrej Pokorny via Lazarus wrote: > On 16.06.2017 9:12, Wolf via Lazarus wrote: >> If the call to "halt;" is commented out, there is no memory leak >> reported. Is this intentional? > Yes, halt kills the program without finalizing anything. No code is > executed afterwards. Everything that is allocated at the time Halt is > executed results in a memory leak. Halt calls the finalization sections. Mattias

Reply by email

Mattias Gaertner
to Wolf
Now I am nicely confused: If halt does call finalization sections, isn't then all heap space requested by the system unit supposed to be freed as well?

The system unit is special. It is loaded even before the heap manager is initialized. Heaptrc does not report memory of the system unit.

Heaptrc reports allocations after its initialization, which is usually right after the system unit.

Mattias

Reply by email

Wolf
to Mattias Gaertner

If I understand you correctly, because
1. command line parameters are internally treated as a null-terminated string (i.e. AnsiString), a call to ParamStr() implies a heap allocation and thus,
2. since ParamStr() is handled by the system unit, a call to halt will result in a memory leak because Heaptrc is not aware of this allocation.

If this is correct, then the conclusion has to be that Heaptrc cannot be trusted as a debugging tool because it is ill-informed about what the system unit is up to.

wolf (rather disillusioned)

Mattias Gaertner wrote 14 lines
On Fri, 16 Jun 2017 20:36:54 +1200 Wolf via Lazarus wrote: > Now I am nicely confused: If halt does call finalization sections, isn't > then all heap space requested by the system unit supposed to be freed as > well? The system unit is special. It is loaded even before the heap manager is initialized. Heaptrc does not report memory of the system unit. Heaptrc reports allocations after its initialization, which is usually right after the system unit. Mattias

Reply by email

Joost van der Sluis
to Wolf
Wolf wrote
If I understand you correctly, because 2. since ParamStr() is handled by the system unit, a call to halt will result in a memory leak because Heaptrc is not aware of this allocation.

Only the initialization of the system-unit is done before the heap-manager is in place. So this is no issue.

The memory being allocated for the commandline and it's parameters itself is system-specific. If there is any memory allocated at all.

If this is correct, then the conclusion has to be that Heaptrc cannot be trusted as a debugging tool because it is ill-informed about what the system unit is up to.

Heaptrace is a great debugging-tool. Debugging-tools give you more information to help you find problems. But they can never be trusted. The same holds for any debugger, btw.

The part about the system-unit is incorrect. (See above)

Calling Halt(), is, well... dangerous. On the other hand you should not care about memory-leaks on application exit. But I can imagine that it obfuscates things when you are searching for real memory-leaks.

Try to place your code in a 'try .. finally' block, and call Halt() thereafter. Of even better, in a procedure, and halt after the procedure-call. You have probably problems with implicit try-finally sections, as Mattias pointed out. You can also investigate this by looking at the created assembly. (fpc -an)

Regards,

Joost.

Show quoted text 18 lines
wolf (rather disillusioned) On 16/06/17 20:47, Mattias Gaertner via Lazarus wrote: > On Fri, 16 Jun 2017 20:36:54 +1200 > Wolf via Lazarus wrote: > >> Now I am nicely confused: If halt does call finalization sections, isn't >> then all heap space requested by the system unit supposed to be freed as >> well? > The system unit is special. It is loaded even before the heap manager > is initialized. Heaptrc does not report memory of the system unit. > > Heaptrc reports allocations after its initialization, which is > usually right after the system unit. > > > Mattias

Reply by email

Mattias Gaertner
to Wolf: If I understand you correctly, because 1. command line parameters are internally treated…
Show quoted text 6 lines
If I understand you correctly, because 1. command line parameters are internally treated as a null-terminated string (i.e. AnsiString), a call to ParamStr() implies a heap allocation and thus, 2. since ParamStr() is handled by the system unit, a call to halt will result in a memory leak because Heaptrc is not aware of this allocation.

No, that's not how temporary strings work.

Just move the code in front of your halt into a separate procedure and the mem leaks are gone.

The compiler creates an implicit try..finally to free managed types and since Halt skips the finally parts the strings are not freed.

If this is correct, then the conclusion has to be that Heaptrc cannot be trusted as a debugging tool because it is ill-informed about what the system unit is up to.

Nonsense. This is neither specific to the system unit nor heaptrc. The conclusion is that must not use Halt, when you need try..finally.

Mattias

Reply by email

Wolf
to Mattias Gaertner

Thanks, Mattias and Joost,
now I understand the real bug is in my assumptions on what goes on behind the screens. But that leads to another question: is there any documentation where I can read up on this so that I may improve on my programming, and particular debugging, skills?
wolf

Mattias Gaertner wrote 26 lines
On Fri, 16 Jun 2017 21:43:38 +1200 Wolf via Lazarus wrote: > If I understand you correctly, because > 1. command line parameters are internally treated as a null-terminated > string (i.e. AnsiString), a call to ParamStr() implies a heap allocation > and thus, > 2. since ParamStr() is handled by the system unit, a call to halt will > result in a memory leak because Heaptrc is not aware of this allocation. No, that's not how temporary strings work. Just move the code in front of your halt into a separate procedure and the mem leaks are gone. The compiler creates an implicit try..finally to free managed types and since Halt skips the finally parts the strings are not freed. > If this is correct, then the conclusion has to be that Heaptrc cannot be > trusted as a debugging tool because it is ill-informed about what the > system unit is up to. Nonsense. This is neither specific to the system unit nor heaptrc. The conclusion is that must not use Halt, when you need try..finally. Mattias

Reply by email

Joost van der Sluis
to Wolf

Op 16-06-17 om 22:58 schreef Wolf via Lazarus:

now I understand the real bug is in my assumptions on what goes on behind the screens. But that leads to another question: is there any documentation where I can read up on this so that I may improve on my programming, and particular debugging, skills?

Well, it's not that this behavior is hidden. It's even documented: https://www.freepascal.org/docs-html/ref/refch17.html. So you could read the pure documentation....

There's also a wiki about this issue:
http://wiki.freepascal.org/Avoiding_implicit_try_finally_section

But I doubt that this is what you meant.

You asked this on the Lazarus-list, but this is more a question for the fpc-pascal list. What you could do is follow this list, or maybe even fpc-devel. You can also browse the archives.

You can learn a lot from there.

Regards,

Joost.

Reply by email

Joost van der Sluis
to Wolf: now I understand the real bug is in my assumptions on what goes on behind the screens.…

Op 16-06-17 om 22:58 schreef Wolf via Lazarus:

now I understand the real bug is in my assumptions on what goes on behind the screens. But that leads to another question: is there any documentation where I can read up on this so that I may improve on my programming, and particular debugging, skills?

Well, it's not that this behavior is hidden. It's even documented: https://www.freepascal.org/docs-html/ref/refch17.html. So you could read the pure documentation....

There's also a wiki about this issue:
http://wiki.freepascal.org/Avoiding_implicit_try_finally_section

But I doubt that this is what you meant.

You asked this on the Lazarus-list, but this is more a question for the fpc-pascal list. What you could do is follow this list, or maybe even fpc-devel. You can also browse the archives.

You can learn a lot from there.

Regards,

Joost.

Reply by email

Wolf
to Joost van der Sluis

Now that I learned the word "initialization section", I could google for it, and what's going on behind the screens is no longer murky. Thanks again. I even found the heaptrc documentation
<https://www.freepascal.org/docs-html/rtl/heaptrc/index.html> and in it the "dumpheap" procedure, which means I can follow heap usage throughout my program, without any interference from "halt".
--Problem solved--.
wolf

Joost van der Sluis wrote 26 lines
Op 16-06-17 om 22:58 schreef Wolf via Lazarus: > now I understand the real bug is in my assumptions on what goes on > behind the screens. But that leads to another question: is there any > documentation where I can read up on this so that I may improve on my > programming, and particular debugging, skills? Well, it's not that this behavior is hidden. It's even documented: https://www.freepascal.org/docs-html/ref/refch17.html. So you could read the pure documentation.... There's also a wiki about this issue: http://wiki.freepascal.org/Avoiding_implicit_try_finally_section But I doubt that this is what you meant. You asked this on the Lazarus-list, but this is more a question for the fpc-pascal list. What you could do is follow this list, or maybe even fpc-devel. You can also browse the archives. You can learn a lot from there. Regards, Joost.

Reply by email