<div dir="auto"><div><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Michael Van Canneyt via fpc-devel <<a href="mailto:fpc-devel@lists.freepascal.org">fpc-devel@lists.freepascal.org</a>> schrieb am Do., 20. Juli 2023, 19:24:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
<br>
On Thu, 20 Jul 2023, Martin Frb via fpc-devel wrote:<br>
<br>
> For const param, it is well documented that the value (that includes the <br>
> variable that is passed) must not be changed.<br>
><br>
> But for "var param"?<br>
><br>
> Well maybe, but not explicit<br>
> <a href="https://www.freepascal.org/docs-html/ref/refsu68.html#x184-20800014.4.5" rel="noreferrer noreferrer" target="_blank">https://www.freepascal.org/docs-html/ref/refsu68.html#x184-20800014.4.5</a><br>
> >> Open parameters can be passed by value, by reference or as a <br>
> constant parameter. In the latter cases the procedure receives a pointer <br>
> to the actual array.<br>
><br>
> So a user with sufficient experience could detect that if a pointer is <br>
> received, then the value which is pointed to must not be changed.<br>
><br>
> Maybe that should be mentioned more explicitly.<br>
> And maybe it should additionally also be mentioned on <br>
> <a href="https://www.freepascal.org/docs-html/ref/refsu65.html" rel="noreferrer noreferrer" target="_blank">https://www.freepascal.org/docs-html/ref/refsu65.html</a><br>
><br>
><br>
> Because the below may be unexpected to quite a few users.<br>
><br>
> It will (at least on my test on windows / of course depends on mem <br>
> manager) print numbers starting at 300.<br>
> Even so 200++ has been assigned.<br>
><br>
> But (with sufficient luck or lack of luck) "y" will re-use the memory of <br>
> "x". And "a" will then change "y" which may not be expected.<br>
><br>
><br>
> program Project1;<br>
> {$mode objfpc}<br>
><br>
> var x,y: array of integer;<br>
>   i: Integer;<br>
><br>
> procedure foo(var a: array of integer);<br>
> var<br>
>   j: Integer;<br>
> begin<br>
>   x := nil;<br>
>   SetLength(y, 10);<br>
>   for j := 0 to 9 do y[j] := 200+j;<br>
><br>
>   for j := 0 to 9 do a[j] := 300+j;<br>
> end;<br>
><br>
> begin<br>
>   SetLength(x, 10);<br>
>   for i := 0 to 9 do x[i] := 100+i;<br>
>   foo(x);<br>
>   for i := 0 to 9 do writeln(y[i]);<br>
>   readln;<br>
> end.<br>
<br>
It's IMO probably better to outright forbid passing open array by reference.<br></blockquote></div></div><div dir="auto"><br></div><div dir="auto">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. </div><div dir="auto"><br></div><div dir="auto"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
printing length(a) after x:=Nil; gives 10, which is simply wrong.<br></blockquote></div></div><div dir="auto"><br></div><div dir="auto">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). </div><div dir="auto"><br></div><div dir="auto">Regards, </div><div dir="auto">Sven </div><div dir="auto"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
</blockquote></div></div></div>