Recent

Author Topic: Dynamic arrays are automatically deallocated?  (Read 12157 times)

Tommi

  • Full Member
  • ***
  • Posts: 213
Dynamic arrays are automatically deallocated?
« on: September 24, 2017, 12:33:48 pm »
I noted that sometime when I enter in a function where is declared a dynamic array, it remembers the old content.

In cases as below:
Quote
function myfunction(a:string;b:string):integer;
var
  myArray:array of integer;
  resultingString:string;
  a:integer;
begin
 for a:= 1 to 100 do
 begin
    ... code of the loop...
  setLength(myArray,length(myArray)+1);
  myArray[length(myArray)-1]:=resultingString;
 end;
end;
... code of the function ...

I have to put setLength(myArray,0); at the beginning of the function to have everything working.

The point is : if the memory manager deallocates resources declare in var when the functions end, why have I to put setLength(myArray,0); ? Is the memory still reserved ?

Thank you

ps. I know that generally TStringList is better than arrays of strings but it is more difficult to manage the memory in cases of try-except-exit blocks.
« Last Edit: September 24, 2017, 12:57:31 pm by Tommi »

guest58172

  • Guest
Re: Dynamic arrays are automatically deallocated?
« Reply #1 on: September 24, 2017, 12:51:46 pm »
At first glance i'd say that your problem is that "myArray" is not initialized, so that it can have a random initial length when you don't add "setLength(myArray,0);" at the beginning.

Also note: between two calls, the local variables don't share the same memory (it can happens though). A new stack frame is allocated for each call. What can happen is that the heap memory used by a stack variable (such as your array) get reused, but it's UB. You cant rely on that.


Tommi

  • Full Member
  • ***
  • Posts: 213
Re: Dynamic arrays are automatically deallocated?
« Reply #2 on: September 24, 2017, 12:56:34 pm »
Ok, thank you.

guest58172

  • Guest
Re: Dynamic arrays are automatically deallocated?
« Reply #3 on: September 24, 2017, 01:04:34 pm »
By the way:

1. The fact that some heap memory get deallocated doesn't mean that it's filled with 0. Same thing when a block is allocated. That's why old garbages, that look valid, can still be here when a new block is allocated.

2. Look at the compiler warnings. I'm sure there was a warning for your array, something like "...doesn't seem to be initialized".

rvk

  • Hero Member
  • *****
  • Posts: 6110
Re: Dynamic arrays are automatically deallocated?
« Reply #4 on: September 24, 2017, 01:06:35 pm »
Or just do a setLength(myArray, 100); above the loop. It's better that way anyway. Using setLength(myArray, length(myArray) + 1); inside the loop will be very inefficient here (because you already know the loop size and you can use A-1 for index).

guest58172

  • Guest
Re: Dynamic arrays are automatically deallocated?
« Reply #5 on: September 24, 2017, 01:15:05 pm »
If you look at his code there's no guarantee that the array size will be always 100. But if it's the case you're right.

rvk

  • Hero Member
  • *****
  • Posts: 6110
Re: Dynamic arrays are automatically deallocated?
« Reply #6 on: September 24, 2017, 01:34:02 pm »
If you look at his code there's no guarantee that the array size will be always 100. But if it's the case you're right.
The code was:
Code: Pascal  [Select][+][-]
  1. for a:= 1 to 100 do
  2. begin
  3.     ... code of the loop...
  4.   setLength(myArray,length(myArray)+1);
  5.   myArray[length(myArray)-1]:=resultingString;
  6. end;
For me that guarantees that myArray will have 100 elements.
There is no break-out in that code (unless it is in code we don't see).

guest58172

  • Guest
Re: Dynamic arrays are automatically deallocated?
« Reply #7 on: September 24, 2017, 03:38:44 pm »
Unless there's a   

Code: Pascal  [Select][+][-]
  1. if something then continue;

before (i.e in "... code of the loop...").

rvk

  • Hero Member
  • *****
  • Posts: 6110
Re: Dynamic arrays are automatically deallocated?
« Reply #8 on: September 24, 2017, 03:53:30 pm »
Unless there's a   
Code: Pascal  [Select][+][-]
  1. if something then continue;
before ;)  (i.e in "... code of the loop...")
Ah, yes, true, there you have a point  :)

In that particular case I might be tempted to do a setlength for 100 and after the loop, reduce that to whatever was needed. I'm not sure what the fragmentation and efficiency implications there are if you do a lot (100+ or even 1000+) of setlength(length+1)'s.

guest58172

  • Guest
Re: Dynamic arrays are automatically deallocated?
« Reply #9 on: September 24, 2017, 04:18:49 pm »
We don't have the code that's before the array thing anyway...only OP can say if you're right.

Mr.Madguy

  • Hero Member
  • *****
  • Posts: 844
Re: Dynamic arrays are automatically deallocated?
« Reply #10 on: September 24, 2017, 04:54:58 pm »
Not sure about Lazarus, but in Delphi everything is managed automatically, cuz dynamic arrays are essentially the same thing, as strings there. I.e. dynamic array is automatically initialized to have zero length (it's actually pointer and it's simply set to Nil in this case) and it's always initialized with zeros, when length is changed. And also dynamic array is automatically deallocated at the end of procedure (it's reference counted though). And I think, that in Lazarus they should work exactly the same way.
« Last Edit: September 24, 2017, 05:07:52 pm by Mr.Madguy »
Is it healthy for project not to have regular stable releases?
Just for fun: Code::Blocks, GCC 13 and DOS - is it possible?

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: Dynamic arrays are automatically deallocated?
« Reply #11 on: September 24, 2017, 05:10:27 pm »
I have to put setLength(myArray,0); at the beginning of the function to have everything working.

or:
Code: Pascal  [Select][+][-]
  1. var
  2.   myArray:array of integer = nil;

sam707

  • Guest
Re: Dynamic arrays are automatically deallocated?
« Reply #12 on: September 24, 2017, 05:36:12 pm »
Not sure about Lazarus, but in Delphi everything is managed automatically, cuz dynamic arrays are essentially the same thing, as strings there. I.e. dynamic array is automatically initialized to have zero length (it's actually pointer and it's simply set to Nil in this case) and it's always initialized with zeros, when length is changed. And also dynamic array is automatically deallocated at the end of procedure (it's reference counted though). And I think, that in Lazarus they should work exactly the same way.

didn't know dat dynarrays were reference counted like strings, maybe there is a UniqueArray to ensure referencing! OMG MadDude AGAIN: the God of ... HHAHAHHA

Back to my pink tutu...

I should NEVER trust what I read from such 'god'

https://www.freepascal.org/docs-html/rtl/system/uniquestring.html
« Last Edit: September 24, 2017, 05:38:38 pm by sam707 »

sam707

  • Guest
Re: Dynamic arrays are automatically deallocated?
« Reply #13 on: September 24, 2017, 05:43:03 pm »
http://wiki.freepascal.org/Dynamic_array

the use of dynamic arrays is simple when they are used in local vars of procs and funcs

1) setlength => alloc array
2) use it inside proc/func
3) on exit proc/func/ OR Block of Code using dyn arrays, setting them to 'nil' just clarify your code (also works in a try .. finally block because it is OPTIONAL see link above, they are auto deallocated on procs/funcs exit

that's all

Quote from wiki link above
"From a memory management view, dynamic array variables are simple pointers. SetLength allocates and frees memory on the heap as needed. When used in functions or procedures only the pointer is added to the stack. When the procedure exits, the dynamic array variable is removed and the memory is made available again. In fact, the memory management procedures are inserted in the executable program and the result is totally transparent to the programmer."
« Last Edit: September 24, 2017, 05:50:08 pm by sam707 »

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Dynamic arrays are automatically deallocated?
« Reply #14 on: September 24, 2017, 05:59:38 pm »
At first glance i'd say that your problem is that "myArray" is not initialized, so that it can have a random initial length when you don't add "setLength(myArray,0);" at the beginning.

This is indeed the principal problem.
FPC sets the length of most dynamic arrays (including strings) on initialization to zero reliably.
However, for dynamic arrays of Integer and Byte (and possibly other types) the array Length() after (compiler) initialization is non-zero. In my testing it is not random, but this may just be an artefact of my system, and anyway is undocumented and presumably implementation-dependent.
The bottom line is that all dynamic arrays, and particularly arrays of Byte or arrays of Integer should be initialised by the programmer either by assigning Nil to the array or using an explicit SetLength(xxx, 0).

 

TinyPortal © 2005-2018