Forum > General
Magic, non referenced variable changes it's value
Fibonacci:
I was coding today and something strange happened. Somehow at some point part of my string was changed although I wasn't changing it (so I thought...)
Long story short, the string was changed, but by different function, which I didn't pass the variable as pointer or "var s: string"
I quickly came to the conclusion, if function is "inline" then parameters variables are passed as reference/pointer, but not always!
I wrote this POC code to show it in action. The strangest thing is the TWO functions MUST be inlined for the "magic" to happen, why is that? Is this kind of behavior documented somewhere? Some FPC dev shall explain?
Request: I don't have Delphi and I'm curious, please compile this code and post here if the string was replaced to "magic".
Quick poll: did you know about this? I didn't.
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---program magic; procedure test(s: string); inline;begin //this procedure actually does nothing //it just changes it's "s" variable (copy of?) to "magic" s := 'magic';end; procedure main; inline;var some_string: string;begin //set some string some_string := 'some value'; //call function that "does nothing" test(some_string); //expected "some value", shows "magic" writeln(some_string); readln;end; begin main;end.
It's not because it's string, it does the same with any type, lets check integer:
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---program magic; procedure test(x: integer); inline;begin x := 1234;end; procedure main; inline;var int_test: integer;begin //set some integer int_test := 555; //call function that "does nothing" test(int_test); //expected "555", shows "1234" writeln(int_test); readln;end; begin main;end.
Regards
Fibonacci:
Compiled in Delphi, different result. Works as expected. So seems like a bug in FPC.
Blaazen:
Report it on GitLab. BTW, I have also opened one ticket about inlining: https://gitlab.com/freepascal.org/fpc/source/-/issues/40158
Red_prig:
I have seen something similar, so you have to be careful with inline procedures
WooBean:
@Fibonacci
« on: May 25, 2023, 01:15:06 am »
Well, so we have problem when calling inlined procedure inside inlined procedure when this called one (procedure/function) can change parameter(s) declared as value parameter(s). This behaviour of FPC breaks the statement obout parameters:
"When parameters are declared as value parameters, the procedure gets a copy of the parameters that the calling statement passes. Any modifications to these parameters are purely local to the procedure’s block, and do not propagate back to the calling block."
One more observation, documentation says that inlining is disabled by default and needs to be activated by directive {$INLINE ON} or commandline switch [-Si]. This option can be set inside Lazarus configuration. Actually (for Lazarus 2.2.0/FPC 3.2.2) inlining is accessible without it (for mode objFPC or delphi and 64/32 target).
Navigation
[0] Message Index
[#] Next page