[fpc-devel] Managed Types, Undefined Bhaviour

Jonas Maebe jonas at freepascal.org
Fri Jun 29 22:33:44 CEST 2018


On 29/06/18 22:02, Stefan Glienke wrote:
> If I am not mistaken (this is from my observarion and might not be 100% 
> accurate) usually the rule in Delphi (possibly similar in FPC) when it 
> allows to directly pass the LHS as hidden result parameter is when it is 
> a local variable.

FPC does it when it knows for certain the target cannot be read or 
modified by the called function. Even for local variables, this is not 
always the case, e.g. if the local variable's address may have been 
taken at some point: by the address parameter, or simply because it was 
passed as var- or out-parameter (the called function could then take the 
address of that parameter and store it elsewhere). I.e., it is based on 
alias analysis.

With whole-program analysis, it could also be done with global 
variables, or in cases the compiler could prove that the function that 
received a (local) variable as var/out-parameter did not take its 
address and store it in a location that survived the lifetime of the 
called function.

That's what I meant when I said this proposal defines language behaviour 
based on the limitations of a compiler's implementation of alias 
analysis. Nobody can be 100% accurate about this because this can change 
from one compiler version to another, unless you limit yourself to the 
very first implementation your original compiler had. Any improvement 
could break working code.

> Now with the dynamic array we have the case that since 
> the content of the temp variable was being copied it then when being 
> reused has a ref count of 1 causing SetLength to just realloc the memory 
> and possibly keep any existing content of the array copying it then on 
> to the LHS of a second statement as shown in the code example earlier.

I fully agree it is counter-intuitive. But I disagree that only solving 
the issue in specific cases (which aren't even documented anywhere) is a 
solution. Either you go all the way, or you don't do it.

Having the programmer keep manual track of when a managed type might 
need extra initialisation does not make sense. After all, when you 
change your code, behaviour could change because suddenly a local 
variable might have a value at a point where previously it didn't. 
Having to follow all code paths to see whether somewhere you call a 
function that does not initialise its function result so you can add an 
extra nil-initialisation of that managed local variable is the opposite 
of robust code.

> IMO there is a potential cause for a code defect that is not obvious - 
> you might go the way of the principle of least surprises and try to 
> address it

The principle of least surprises would be to always use temps and to 
always initialise them before passing them as function result. I think 
many more people would expect this rather than "it is usually 
initialised to nil". It would of course result in complaints that FPC 
performs extra initialisations of managed variables compared to Delphi.

> or argue it away for whatever reasons.

That is no way to discuss.


Jonas



More information about the fpc-devel mailing list