Weird behavior (or bug) when a STRING is passed BYVAL to a function returning BYREF
Complex objects (for example with destructors) are always passed BYREF. In case of BYVAL they will be copied to a temporary object, but that is then still passed BYREF implicitly, so that the destructor can be called from within the caller's context, after the callee returns.
The following example shows that:
- (1): the temporary object (reference) can be use safely in an expression's code that includes the call,
- (2): after call expression, the temporary object (reference) is no more usable because destructed after expression evaluation,
- (3): the original object is not modified.
Code: Select all
Type UDT
Dim As String s = "freeBASIC"
End Type
Function f (Byval u As UDT) Byref As UDT
u.s &= " version 0.91.0"
Return u
End Function
Dim As UDT u
Print "(1):"
Print "'" & f(u).s & "'"
Print "'" & (@(f(u)))->s & "'"
Print: Print "(2):"
Dim As UDT Ptr p = @(f(u))
Print "'" & p->s & "'"
Print: Print "(3):"
Print "'" & u.s & "'"
Sleep
Code: Select all
(1):
'freeBASIC version 0.91.0'
'freeBASIC version 0.91.0'
(2):
''
(3):
'freeBASIC'
For the STRING that is a pseudo object with destructor, the functioning should be the same:
- BYVAL AS STRING is now working properly: it now has BYVAL semantics and no longer behaves like BYREF AS ZSTRING. Modifications made by the callee are not visible to the caller, as for other BYVAL parameters. (BYVAL AS STRING is implemented by copying the string argument into a temporary STRING, whose descriptor is then passed BYREF to the procedure).
But the following example shows that the temporary string (reference) is never usable, even inside the call expression:
Code: Select all
Function f (Byval s As String) Byref As String
s &= " version 0.91.0"
Return s
End Function
Dim As String s = "freeBASIC"
Print "(1):"
Print "'" & f(s) & "'"
Print "'" & *(@(f(s))) & "'"
Print: Print "(2):"
Dim As String Ptr p = @(f(s))
Print "'" & *p & "'"
Print: Print "(3):"
Print "'" & s & "'"
Sleep
Code: Select all
(1):
''
''
(2):
''
(3):
'freeBASIC'
Even the simplest 'Print f(s)' fails!