The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 2,119 other followers

Can we truly assert that an array returned from a function is always a true copy?

Posted by jpluimers on 2020/09/23

The answer is no: [WayBack] Hi all, Can we truly assert that an array returned from a function is always a new true copy and that this is guaranteed to not change in between compil… – Ugochukwu Mmaduekwe – Google+

From Primož book and comment:

Depending on how you create this array.

For example, the following code outputs 42, not 17.

program Project142;

{$APPTYPE CONSOLE}

{$R *.res}

uses
System.SysUtils;

function Bypass(const a: TArray<integer>): TArray<integer>;
begin
Result := a;
end;

var
a, b: TArray<integer>;

begin
SetLength(a, 1);
a[0] := 17;
b := Bypass(a);
a[0] := 42;
Writeln(b[0]);
Readln;
end.

You can use `SetLength(arr, Length(arr))` to make array unique. Changing Bypass to the following code would make the test program emit 17.

function Bypass(const a: TArray<integer>): TArray<integer>;
begin
Result := a;
SetLength(Result, Length(Result));
end;

–jeroen

One Response to “Can we truly assert that an array returned from a function is always a true copy?”

  1. I would not rely on SetLength() for this. Forcing an array’s refcount to 1 during a resize, even if to the same length, is an implementation detail, not a guaranteed contract.

    In XE7 and later, the System unit has a public DynArrayUnique() function to ensure a dynamic array’s refcount is 1, similar to System.UniqueString() for strings, eg something like this (I’m not sure if this is 100% correct, as I don’t have the source on hand to look at):

    Result := a;
    DynArrayUnique(Pointer(Result), TypeInfo(Integer));

    Alternatively, you can just use System.Copy() instead, eg:

    Result := Copy(a, 0, Length(a));

    Or simply:

    Result := Copy(a);

    Either way would make the code more self-documenting that a copy of the source dynamic array is begin made explicitly, rather than SetLength() making a copy implicitly.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

 
%d bloggers like this: