* * *

Author Topic: Pushing record to heap (Basic Question)  (Read 1193 times)

BrainChemistry

  • Jr. Member
  • **
  • Posts: 65
Pushing record to heap (Basic Question)
« on: June 08, 2018, 06:30:28 pm »
Hi there,

let's assume you have a large record.

Code: Pascal  [Select]
  1. ExampleRecord = record
  2.   entry1: Integer;
  3.   entry2: AnotherRecord;
  4.   entry3: array[0..1024] of Boolean;
  5.   .
  6.   .
  7.  
  8. end;
  9.  

Well, in case of making the ExampleRecord part of a dyn. array, it would be completly pushed into the heap (is that true?). Let's assume I just need one instance of this record, it would be stored in the stack.

What can I do now to get it pushed to the heap?

If I do this

Code: Pascal  [Select]
  1. New(@ExampleRecord);
  2.  

what follows for the elements of the array or the fields of AnotherRecord? Are the elements and the fields on the heap, too?

Thaddy

  • Hero Member
  • *****
  • Posts: 7136
Re: Pushing record to heap (Basic Question)
« Reply #1 on: June 08, 2018, 06:46:13 pm »
Hi there,

let's assume you have a large record.

Code: Pascal  [Select]
  1. ExampleRecord = record
  2.   entry1: Integer;
  3.   entry2: AnotherRecord;
  4.   entry3: array[0..1024] of Boolean;
  5.   .
  6.   .
  7.  
  8. end;
  9.  

Well, in case of making the ExampleRecord part of a dyn. array, it would be completly pushed into the heap (is that true?). Let's assume I just need one instance of this record, it would be stored in the stack.
If it is a global record, YES, heap, if it is local to a procedure or function, NO, stack!
Quote
What can I do now to get it pushed to the heap?
It isn't!
Quote
If I do this

Code: Pascal  [Select]
  1. New(@ExampleRecord);
  2.  

what follows for the elements of the array or the fields of AnotherRecord? Are the elements and the fields on the heap, too?
You completely misunderstand what's happening. But IF it is a global record or a local pointer to record then yes.. it is on the heap. But if it is declared on the stack the members are also on the stack, unless declared as a pointer to record and new(0 and Dispose() Then it is on the heap. (And inaccessible when declared as local and you forgot to call dispose: memory leak).
When you use the record locally (not the pointer) it will be free'd automatically because it is on the stack (in full) if you use new() and Dispose() locally only the pointer disappears from the stack and you have a memory leak if you do not call dispose.

Note if your record contains members of a managed type, these are always on the heap (Like AnsiStrings, classes and interfaces). Even if the record is on the stack.
« Last Edit: June 08, 2018, 06:54:39 pm by Thaddy »
inline variables like in D10.3 are a bit like Brexit: if you are given the wrong information it sounds like a good idea. Every kid loves candy, but it makes you fat and your teeth will disappear.

BrainChemistry

  • Jr. Member
  • **
  • Posts: 65
Re: Pushing record to heap (Basic Question)
« Reply #2 on: June 09, 2018, 02:35:41 am »
Hi Thaddy,
thanks for your reply!

Well, in case of making the ExampleRecord part of a dyn. array, it would be completly pushed into the heap (is that true?). Let's assume I just need one instance of this record, it would be stored in the stack.
If it is a global record, YES, heap, if it is local to a procedure or function, NO, stack!

If I do this

Code: Pascal  [Select]
  1. New(@ExampleRecord);
  2.  

what follows for the elements of the array or the fields of AnotherRecord? Are the elements and the fields on the heap, too?
You completely misunderstand what's happening. But IF it is a global record or a local pointer to record then yes.. it is on the heap. But if it is declared on the stack the members are also on the stack, unless declared as a pointer to record and new(0 and Dispose() Then it is on the heap. (And inaccessible when declared as local and you forgot to call dispose: memory leak).
When you use the record locally (not the pointer) it will be free'd automatically because it is on the stack (in full) if you use new() and Dispose() locally only the pointer disappears from the stack and you have a memory leak if you do not call dispose.

Note if your record contains members of a managed type, these are always on the heap (Like AnsiStrings, classes and interfaces). Even if the record is on the stack.
I messed up the second code snippet since I was in a hurry on writing, sorry for that inconvenience. It should better have read like this:
Code: Pascal  [Select]
  1. PExampleRecord = ^ExampleRecord // type sec.
  2. .
  3. .
  4. New(PExampleRecord); // begin..end. sec.
  5.  

Well, about your description I try to translate it into code and I'd appreciate to learn if my assumptions about the used memory is correct.
Code: Pascal  [Select]
  1. //global var sec.
  2. var  
  3.   MyGlobalRecord: ExampleRecord;
  4.  
  5. .
  6. .
  7. // procedure declaration
  8. procedure AProcedure;
  9. var
  10.   MyLocalRecord: ExampleRecord;
  11.   PMyLocalRecord: ^ExampleRecord;
  12. .
  13. .
  14. New(PMyLocalRecord); // the record and all its members are on the heap
  15. .
  16. .
  17. MyLocalRecord := AnotherRecord; // MyLocalRecord and all its members are on the stack
  18.  
  19. // begin..end. block
  20. begin
  21.   MyGlobalRecord := AnotherRecord; // MyGlobalRecord and all its members are on the heap  
  22. end.
  23.  
« Last Edit: June 09, 2018, 02:39:32 am by BrainChemistry »

Thaddy

  • Hero Member
  • *****
  • Posts: 7136
Re: Pushing record to heap (Basic Question)
« Reply #3 on: June 09, 2018, 09:01:01 am »
Here's a summary program.
Use the debugger to see the different behavior.
Code: Pascal  [Select]
  1. program records;
  2. // example of record behavior
  3. // assumes record without members that need finalization
  4. {$mode objfpc}
  5. type
  6.   PMyRecord = ^TMyRecord;
  7.   TmyRecord = record
  8.   a,b:integer;
  9.   c:string[255];
  10.   end;
  11.  
  12. procedure Localrecord;
  13. var a:TMyRecord;
  14. begin
  15.   //stack allocated;
  16.   a.a := 100;
  17.   a.b := 200;
  18.   a.c := 'Test Local';
  19.   writeln(a.c);
  20. end;
  21. procedure LocalDynamicRecord;
  22. var a:PMyRecord;
  23. begin
  24.   // Pointer on stack record on heap;
  25.   New(a);
  26.   // code
  27.   a^.a := 100;
  28.   a^.b := 200;
  29.   a^.c := 'Test Local Dynamic';
  30.   writeln(a^.c);
  31.   Dispose(a);
  32. end;
  33.  
  34. var
  35.   //heap allocated, no clean up necessary
  36.   GlobalRecord:TMyrecord;
  37.   //dynamically heap allocated, needs clean up.
  38.   GlobalDynamicRecord:PMyRecord;  
  39. begin
  40.   GlobalRecord.a := 100;
  41.   GlobalRecord.b := 200;
  42.   GlobalRecord.c := 'Test Global';
  43.   writeln(GlobalRecord.c);
  44.   New(GlobalDynamicRecord);
  45.   // code
  46.   GlobalDynamicRecord^.a := 100;
  47.   GlobalDynamicRecord^.b := 200;
  48.   GlobalDynamicRecord^.c := 'Test Global Dynamic';
  49.   writeln(GlobalDynamicRecord^.c);
  50.   Dispose(GlobalDynamicRecord);
  51.   LocalRecord;
  52.   LocalDynamicRecord;
  53. end.

« Last Edit: June 09, 2018, 09:07:10 am by Thaddy »
inline variables like in D10.3 are a bit like Brexit: if you are given the wrong information it sounds like a good idea. Every kid loves candy, but it makes you fat and your teeth will disappear.

BrainChemistry

  • Jr. Member
  • **
  • Posts: 65
Re: Pushing record to heap (Basic Question)
« Reply #4 on: June 09, 2018, 02:22:58 pm »
Thanks for your effort, it helped alot!

 

Recent

Get Lazarus at SourceForge.net. Fast, secure and Free Open Source software downloads Open Hub project report for Lazarus