Forum > General

Magic, non referenced variable changes it's value

(1/3) > >>

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

Go to full version