Recent

Author Topic: Why have memory leak const record ?  (Read 716 times)

Thausand

  • Full Member
  • ***
  • Posts: 227
Why have memory leak const record ?
« on: May 06, 2019, 08:36:29 pm »
HI hello,

I have try look why but no can find me and then no understand why have leak this program:
Code: Pascal  [Select]
  1. program test_const_rec;
  2.  
  3. {$MODE OBJFPC}{$H+}
  4.  
  5. Uses
  6.   SysUtils;
  7.  
  8. type
  9.   TDataRecord = record
  10.     test : string;
  11.   end;
  12.  
  13. procedure MakeMany(var DataRecord: TDataRecord);
  14. const
  15.   Count : integer = 0;
  16. begin
  17.   inc(count);
  18.   DataRecord.test := Count.ToString;
  19. end;
  20.  
  21. procedure Have_leak;
  22. const
  23.   DataRecord : TDataRecord = (test : '');
  24. var
  25.   i : integer;
  26. begin
  27.   DataRecord := default(TDataRecord);
  28.  
  29.   for i := 1 to 100 do
  30.   begin
  31.     MakeMany(DataRecord);
  32.     WriteLn(DataRecord.Test);
  33.   end;
  34. end;
  35.  
  36. procedure Have_no_leak;
  37. var
  38.   i          : integer;
  39.   DataRecord : TDataRecord = (test : '');
  40. begin
  41.   DataRecord := default(TDataRecord);
  42.  
  43.   for i := 1 to 100 do
  44.   begin
  45.     MakeMany(DataRecord);
  46.     WriteLn(DataRecord.Test);
  47.   end;
  48. end;
  49.  
  50.  
  51. begin
  52.   Have_leak;
  53. //  Have_no_leak;
  54. end.
  55.  

heap trace:
Code: [Select]
Heap dump by heaptrc unit
106 memory blocks allocated : 2574/2696
105 memory blocks freed     : 2558/2680
1 unfreed memory blocks : 16
True heap size : 393216
True free heap : 393120
Should be : 393136
Call trace for block $76F6E180 size 16
  $00010284  HAVE_LEAK,  line 31 of test_const_rec.pas
  $000103EC  main,  line 52 of test_const_rec.pas

Maybe some one can help make better understand ?

howardpc

  • Hero Member
  • *****
  • Posts: 3043
Re: Why have memory leak const record ?
« Reply #1 on: May 06, 2019, 08:58:14 pm »
If you make DataRecord a global const, you can ensure that its string field (managed memory) is finalized.
Code: Pascal  [Select]
  1. program test_const_rec;
  2.  
  3. {$MODE OBJFPC}{$H+}
  4.  
  5. Uses
  6.   SysUtils;
  7.  
  8. type
  9.   TDataRecord = record
  10.     test : string;
  11.   end;
  12.  
  13. const
  14.   DataRecord : TDataRecord = (test : '');
  15.  
  16. procedure MakeMany(var DataRecord: TDataRecord);
  17. const
  18.   Count : integer = 0;
  19. begin
  20.   inc(Count);
  21.   DataRecord.test := Count.ToString;
  22. end;
  23.  
  24. procedure This_Now_Has_No_Leak;
  25. var
  26.   i : integer;
  27. begin
  28.   DataRecord := default(TDataRecord);
  29.   for i := 1 to 100 do
  30.   begin
  31.     MakeMany(DataRecord);
  32.     WriteLn(DataRecord.Test);
  33.   end;
  34. end;
  35.  
  36. begin
  37.   This_Now_Has_No_Leak;
  38.   DataRecord.test := ''; // <- insert this
  39.   ReadLn;
  40. end.

Thausand

  • Full Member
  • ***
  • Posts: 227
Re: Why have memory leak const record ?
« Reply #2 on: May 06, 2019, 09:15:59 pm »
Hi hello howardpc,

Many thanksy for help.

If you make DataRecord a global const, you can ensure that its string field (managed memory) is finalized.
Yes. In producing program i have make global const and leak is go away.

Is problem i no understand why  :) (and is smell code have global const)

Ok. Then i read better your answer and i think you write give hint string field and memory finalize ?

I have find that when no use record field type string (or have string short) then no have leak memory ..... i have more look help because i think i have read some thing "managed memory" and "finalize"....

Thank howardpc. I think maybe is good for find answer why.... i try look  :)

Thausand

  • Full Member
  • ***
  • Posts: 227
Re: Why have memory leak const record ?
« Reply #3 on: May 06, 2019, 10:50:34 pm »
I have look and read "typed constants" https://www.freepascal.org/docs-html/ref/refse10.html#x22-210002.2

read:
Quote
Remark: It should be stressed that typed constants are automatically initialized at program start. This is also true for local typed constants and initialized variables. Local typed constants are also initialized at program start. If their value was changed during previous invocations of the function, they will retain their changed value, i.e. they are not initialized each time the function is invoked.
I think that say when program start for typed const is called "initialize". Is no help read "Finalize" typed const.

Then i think have answer why and how can fix:

Code: Pascal  [Select]
  1. procedure Have_leak_stop;
  2. const
  3.   DataRecord : TDataRecord = (test : '');
  4. var
  5.   i : integer;
  6. begin
  7.   DataRecord := default(TDataRecord);
  8.  
  9.   for i := 1 to 100 do
  10.   begin
  11.     MakeMany(DataRecord);
  12.     WriteLn(DataRecord.Test);
  13.   end;
  14.  
  15.   // have auto call Initialize (program startup) and no Finalize. Then make self
  16.   Finalize(DataRecord);
  17. end;
  18. ....
  19.  
I think is little confuse if not know/understand :)

Typed const example is like global variable and no act same global variable ...

Thanksy more howardpc for make write hint.

ASerge

  • Hero Member
  • *****
  • Posts: 1305
Re: Why have memory leak const record ?
« Reply #4 on: May 07, 2019, 03:42:16 am »
A simpler example of a memory leak:
Code: Pascal  [Select]
  1. {$MODE OBJFPC}
  2. {$WRITEABLECONST ON}
  3. {$LONGSTRINGS ON}
  4.  
  5. procedure Test;
  6. const
  7.   Leak: string = 'Some string';
  8. begin
  9.   UniqueString(Leak);
  10. end;
  11.  
  12. begin
  13.   Test;
  14. end.
In my opinion, this is a compiler bug. In Delphi, this code does not cause a memory leak.

Thausand

  • Full Member
  • ***
  • Posts: 227
Re: Why have memory leak const record ?
« Reply #5 on: May 07, 2019, 04:07:10 am »
Hi hello ASerge,

A simpler example of a memory leak:
...
Thanksy. Yes, that much more simple

Quote
In my opinion, this is a compiler bug. In Delphi, this code does not cause a memory leak.
I think same.

I read better:
Quote
Remark: It should be stressed that typed constants are automatically initialized at program start. This is also true for local typed constants and initialized variables. Local typed constants are also initialized at program start. If their value was changed during previous invocations of the function, they will retain their changed value, i.e. they are not initialized each time the function is invoked.
I think than can write sentence after:
Local initialized variable are also initialized at program start.

Then same intialize and no have leak memory when use intialized variable.

Same program ASerge make variable then no leak.

I no have find answer for why differ and need call finalize when use typed const :-\

Some one know ?

Thaddy

  • Hero Member
  • *****
  • Posts: 8226
Re: Why have memory leak const record ?
« Reply #6 on: May 07, 2019, 08:54:34 am »
A simpler example of a memory leak:
Code: Pascal  [Select]
  1. {$MODE OBJFPC}
  2. {$WRITEABLECONST ON}
  3. {$LONGSTRINGS ON}
  4.  
  5. procedure Test;
  6. const
  7.   Leak: string = 'Some string';
  8. begin
  9.   UniqueString(Leak);
  10. end;
  11.  
  12. begin
  13.   Test;
  14. end.
In my opinion, this is a compiler bug. In Delphi, this code does not cause a memory leak.
In my opinion too.. see also here: https://forum.lazarus.freepascal.org/index.php?topic=44552.0
Didn't one of us reported yet? Otherwise plz do... Uniquestring causes that problem and it is not fixed yet.

(I made the mistake there, that I was not convinced because of sheer logic, but eventually I reached the same conclusion based on testing)

With a const record I can not reproduce it with trunk 331-r42017 on armhf.
« Last Edit: May 07, 2019, 09:07:47 am by Thaddy »
Read the manuals and if you are a professional get a proper education in computer science. Makes the forum a lot cleaner.

PascalDragon

  • Sr. Member
  • ****
  • Posts: 450
  • Compiler Developer
Re: Why have memory leak const record ?
« Reply #7 on: May 07, 2019, 09:20:58 am »
Hmm, it seems that the compiler does not generate the finalizer for the unit (or program) if there are only local constants. If I add a global constant then the finalizer is generated for both the global constant and the local one. :(
Please file a bug, preferably with the example by ASerge.

ASerge

  • Hero Member
  • *****
  • Posts: 1305
Re: Why have memory leak const record ?
« Reply #8 on: May 07, 2019, 06:31:20 pm »
This is true for all managed types:
Code: Pascal  [Select]
  1. procedure Test;
  2. const
  3.   Leak: TBoundArray = nil;
  4. begin
  5.   SetLength(Leak, 10);
  6. end;
Code: Pascal  [Select]
  1. procedure Test;
  2. const
  3.   Leak: IInterface = nil;
  4. begin
  5.   Leak := TInterfacedObject.Create as IInterface;
  6. end;

Thausand

  • Full Member
  • ***
  • Posts: 227
Re: Why have memory leak const record ?
« Reply #9 on: May 07, 2019, 09:40:00 pm »
Hmm, it seems that the compiler does not generate the finalizer for the unit (or program) if there are only local constants. If I add a global constant then the finalizer is generated for both the global constant and the local one. :(
Maybe i no read correct (then i sorry). If make add:
Code: [Select]
const
  SomeConst = 'some thing';
  ....
Then have leak no remove example my. Then you write no correct ? I write maybe important i test freepascal release 3.0.4

Quote
Please file a bug, preferably with the example by ASerge.
If is bug then i can ask some one can maybe make report bug ? I make very bad english write.

I make sure write: my program have leak use freepascal release 3.0.4 (install lazarus release 2)

ASerge

  • Hero Member
  • *****
  • Posts: 1305

Thausand

  • Full Member
  • ***
  • Posts: 227
Re: Why have memory leak const record ?
« Reply #11 on: May 07, 2019, 11:09:12 pm »
@ASerge:
very many thank you ASerge  8-)

I not can have write me that many good report  :-[