[fpc-devel] Maybe room for better documentation? open array as var param

Sven Barth pascaldragon at googlemail.com
Thu Jul 20 23:22:26 CEST 2023


Michael Van Canneyt via fpc-devel <fpc-devel at lists.freepascal.org> schrieb
am Do., 20. Juli 2023, 19:24:

>
>
> On Thu, 20 Jul 2023, Martin Frb via fpc-devel wrote:
>
> > For const param, it is well documented that the value (that includes the
> > variable that is passed) must not be changed.
> >
> > But for "var param"?
> >
> > Well maybe, but not explicit
> > https://www.freepascal.org/docs-html/ref/refsu68.html#x184-20800014.4.5
> > >> Open parameters can be passed by value, by reference or as a
> > constant parameter. In the latter cases the procedure receives a pointer
> > to the actual array.
> >
> > So a user with sufficient experience could detect that if a pointer is
> > received, then the value which is pointed to must not be changed.
> >
> > Maybe that should be mentioned more explicitly.
> > And maybe it should additionally also be mentioned on
> > https://www.freepascal.org/docs-html/ref/refsu65.html
> >
> >
> > Because the below may be unexpected to quite a few users.
> >
> > It will (at least on my test on windows / of course depends on mem
> > manager) print numbers starting at 300.
> > Even so 200++ has been assigned.
> >
> > But (with sufficient luck or lack of luck) "y" will re-use the memory of
> > "x". And "a" will then change "y" which may not be expected.
> >
> >
> > program Project1;
> > {$mode objfpc}
> >
> > var x,y: array of integer;
> >   i: Integer;
> >
> > procedure foo(var a: array of integer);
> > var
> >   j: Integer;
> > begin
> >   x := nil;
> >   SetLength(y, 10);
> >   for j := 0 to 9 do y[j] := 200+j;
> >
> >   for j := 0 to 9 do a[j] := 300+j;
> > end;
> >
> > begin
> >   SetLength(x, 10);
> >   for i := 0 to 9 do x[i] := 100+i;
> >   foo(x);
> >   for i := 0 to 9 do writeln(y[i]);
> >   readln;
> > end.
>
> It's IMO probably better to outright forbid passing open array by
> reference.
>

There are valid use cases for that. E.g. multiply a slice of a dynamic
array by two or whatever. And forbidding var would solve nothing, see
below.


> printing length(a) after x:=Nil; gives 10, which is simply wrong.
>

That is true for many cases where you modify the global variable that has
been passed on by reference, e.g. with constant parameters: the compiler
will more often than not pass a reference then, because it's more optional
and the function can't modify it anyway, but if you change the global that
was passed in you get what you deserve... (that's true no matter if it's an
open array, a string or a primitive type).

Regards,
Sven

>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-devel/attachments/20230720/f1206057/attachment.htm>


More information about the fpc-devel mailing list