1

I had code with the basic constructs illustrated by the following:

type
    TDynamicArray = array of double ;

var
    a : TDynamicArray ;

    function Func : TDynamicArray ;

    var
        b : TDynamicArray ;

    begin
    SetLength (B, 3) ;
    b [0] := 0.0 ;
    b [1] := 1.0 ;
    b [2] := 2.0 ;
    Result := b ;   // note 1  -- should use Result := Copy (b, 0, Length (b)) 
    end ;

begin
a := Func ;  // note 2  -- should we (or could we) use a := Copy (Func, 0, Length (Func)) 
end.

It had been working fine until lately when the function started returning empty arrays. I then spot this which enlightens me to the fact that simple assignment isn't correct, I need to use Copy.

Two questions:

  • I realise I need 'Copy' on the line marked Note 1 to assign to the function result. Do I need to use Copy also on the assignment of the function result to array a (line Note 2)?.
  • Why did the compiler allow my construct and what was the compiled code actually doing?

I realise I could try these things and see, but I'm a little spooked by the compiler letting questionable stuff through.

7
  • As an aside, you certainly wouldn't want the Copy (Func, ... as you show in your comment since it would run Func twice. But to your ain issue, I'm not sure how Delphi handles a local dynamic array variable. I would go with the copy to result in the function, or just use result directly. Commented Oct 2, 2013 at 1:36
  • There's no problem with that code, the array is still heap allocated and ref counted. You might as well work directly on the 'result'. Commented Oct 2, 2013 at 1:51
  • @Sertac aaahhh... which code? The real code can't really be structured to work directly on the function result. I need to be able to assign a local array to Result. Commented Oct 2, 2013 at 1:59
  • 1
    @ross - That's fine. Still, what's on the stack is a pointer to the array - the array itself is on the heap. As long as you keep a reference to the array it won't get finalized. The link you refer to does not seem to be related. Commented Oct 2, 2013 at 2:12
  • If you really think you need to copy an array — which isn't as often as you think it is, I promise — note that you don't need to know its length. You can call Copy with just one argument and it will copy the entire array, no matter its length. The documentation even says so. Commented Oct 2, 2013 at 3:00

1 Answer 1

3

There is no reason to use Copy in either of those assignment statements. Normal assignment works fine. When you allocate b, the reference count of the array is 1. When you assign it to Result, the reference count becomes 2. (Personally, I'd just forego b and operate directly on Result from the start.) When the function returns, b goes out of scope and the reference count becomes 1 again. Finally, when the result is assigned to a, nothing happens because Result was actually an alias for a all along. Ultimately, you're left with one unique array, which should be exactly what you intended.

The compiler allowed your code because your code is fine. The compiler recognizes assignments between arrays just as it does assignments between strings and assignments between interface references, and it generates the right code to adjust the reference counts accordingly.

Using Copy would create an entire copy of the array, but you don't need that. Each time you think you need it, it's in a place where you would have immediately discarded the previous copy anyway. Why make a copy when you already have a perfectly good array ready for any use you want?

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.