Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi dynamic array reference counting

Tags:

delphi

Instead of using a geneirc TList<integer> I have decided to use

TSolutions = array of integer;

And then:

function TEuclidMod.gcdExtended(p, q: integer): TSolutions;
var tmpArr: TSolutions;
begin

 SetLength(tmpArr, 3);

 if (q = 0) then
  begin
   tmpArr[0] := p;
   tmpArr[1] := 1;
   tmpArr[2] := 0;
  end
 else
  begin
   vals := gcdExtended(q, modulo(p,q));
   tmpArr[0] := vals[0];
   tmpArr[1] := vals[2];
   tmpArr[2] := vals[1] - vals[2]*floor(p/q);
  end;

 Result := tmpArr;

end;

The variable vals: TSolutions; is declared private in the class and inside the constructor I am setting its length.


I have read on the docwiki that dynamic arrays are ref counted so I don't have to worry about their lifetime. To be sure I have written:

constructor TEuclidMod.Create;
begin

 SetLength(vals, 3);

end;

destructor TEuclidMod.Destroy;
begin

 vals := nil;
 inherited;

end;

So far this should be fine; vals belongs to the class and I free it on the destruction of the class. What about tmpArr?

My function works correctly. The tmpArr is local, then I call SetLength and I give him a lenght: this is creating on the heap the array if I'm not wrong. But then when I return with Result := tmpArr doesn't it get deleted (tmpArr) since the function goes out of scope? I don't want to return a dangling pointer or something else! I need to be sure that it's not freed.

I guess I'm safe because it is a function and it returns a TSolution so the ref count should be always 1 at least. Is it exact? Basically: even if it's local, is it correctly returned?

But from what I've found on SO, in this case

procedure test;
var a: TSolution;
begin

 SetLength(a, 7);
 //do something

end;

The a is always freed when the procedure goes out of scope!

like image 769
Emma Rossignoli Avatar asked Aug 30 '17 11:08

Emma Rossignoli


1 Answers

Dynamic arrays are reference counted. Don't worry about their memory management - just use them; that's what reference counting is for. You don't have to nil the class fields in the destructor. The compiler will remove their reference counts when the object is destroyed.

But then when I return with Result := tmpArr doesn't it get deleted (tmpArr) since the function goes out of scope?

Well, no, because you've returned the array by assigning it to Result and, presumably, the caller is also assigning the result to a new variable in turn. The reference count naturally will remain at least one unless the caller does not also assign the function result to a new variable.

like image 173
J... Avatar answered Nov 01 '22 18:11

J...