Bug when appending return value of procedure to a string

Just starting out? Need help? Post your questions and find answers here.
NilsH
New User
New User
Posts: 8
Joined: Sun Apr 16, 2017 8:46 pm
Location: Germany

Bug when appending return value of procedure to a string

Post by NilsH »

Hi!

I think I found a bug in the PureBasic compiler.
When modifying a string variable from within a procedure that returns a string
and then appending the returned string to the same variable,
the modifications done by the procedure are lost.
I'm using PureBsic 5.60 64 bit on Windows 7 SP1 64 bit.
The following code will demonstrate this problem:

Code: Select all

Procedure.s returnstring(*s.String)
  *s\s + "abc"
  ProcedureReturn "xyz"
EndProcedure

*mystr.String = AllocateStructure(String)

; This is line optional.
; The bug is independent of whether a value has been assigned to the string or not.
*mystr\s = "123" 

; This is where the bug occurs.
; This line calls the function returnstring() which first appends "abc" and then returns "xyz".
; When the returned string is appended, the "abc" is lost.
*mystr\s + returnstring(*mystr)

; This is a workaround using a temporary string.
; temp$ = returnstring(*mystr)
; *mystr\s + temp$

; Should be "123abcxyz", but is actually "123xyz".
Debug *mystr\s
The above example uses a string member of a dynamically allocated structure, because this is what my actual program does as well.
However, the bug also occurs when using a simple global variable, like in the follwing example:

Code: Select all

Global string$

Procedure.s returnstring()
  string$ + "abc"
  ProcedureReturn "xyz"
EndProcedure

string$ = "123"

string$ + returnstring()

; Should be "123abcxyz"
Debug string$
I hope this is a bug (and not a feature :)) and that it will get fixed soon, but there's no hurry.

Cheers
Nils
freak
PureBasic Team
PureBasic Team
Posts: 5929
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Re: Bug when appending return value of procedure to a string

Post by freak »

Its not a bug, it is the expected behavior.

Code: Select all

*mystr\s + returnstring(*mystr)
This is just a short form for:

Code: Select all

*mystr\s = *mystr\s + returnstring(*mystr)
Expressions are evaluated left to right, so to compute the value that is placed inside the final result, the first thing that is evaluated is *mystr\s which at this point only holds the value "123". The procedure is called after this part has been evaluated. This means no matter what you do inside the procedure to *mystr\s, it cannot have an effect on the result since this part has already been evaluated by the time the procedure is called.

It is a simple result of the evaluation rules and no bug.
quidquid Latine dictum sit altum videtur
NilsH
New User
New User
Posts: 8
Joined: Sun Apr 16, 2017 8:46 pm
Location: Germany

Re: Bug when appending return value of procedure to a string

Post by NilsH »

freak wrote:Its not a bug, it is the expected behavior.
Okay, now I understand the reason for this behavior, but I still think it's confusing,
because when I see something like "a + b()" I wouldn't expect that the compiler understands it as "a = a + b()".
The documentation unfortunately is not very clear about this topic. Only this example

Code: Select all

  Dim MyArray(10)
  MyArray(Random(10)) + 1 ; The same as: MyArray(Random(10)) = MyArray(Random(10)) + 1, but here Random() won't return the same value for each call.
might give a hint about the problem.

Nils
DontTalkToMe
Enthusiast
Enthusiast
Posts: 334
Joined: Mon Feb 04, 2013 5:28 pm

Re: Bug when appending return value of procedure to a string

Post by DontTalkToMe »

You are not alone :lol:

http://www.purebasic.fr/english/viewtop ... 12&t=51251

I think the example you mentioned was written in reply to the thread above
freak
PureBasic Team
PureBasic Team
Posts: 5929
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Re: Bug when appending return value of procedure to a string

Post by freak »

I just used the long form for explanation. The behavior is a result of the expression evaluation order and has actually nothing to do with how the short form is treated. Since the procedure is the second thing in the expression, it cannot affect the parts of the expression that were already evaluated. It works like that in pretty much any language.

Don't believe me? Try the same in C or Java and tell me the result ;)
quidquid Latine dictum sit altum videtur
NilsH
New User
New User
Posts: 8
Joined: Sun Apr 16, 2017 8:46 pm
Location: Germany

Re: Bug when appending return value of procedure to a string

Post by NilsH »

Just tried it.

Code: Select all

#include <stdio.h>

int myfunc(int *intptr) {
   *intptr += 200;
   return 10;
}

int main(int argc, char *argv[]) {

   int myint = 3000;
   myint = myint + myfunc(&myint);
   printf("myint = %i\n", myint);

   return 0;

}
C code compiled with Pelles C wrote:myint = 3210
Probably it's a just very bad idea to modify a variable within a function that is called in an expression that uses the same variable.
I guess the result of this is simply undefined because of unpredictable optimizations done by the C compiler.

Nils
DontTalkToMe
Enthusiast
Enthusiast
Posts: 334
Joined: Mon Feb 04, 2013 5:28 pm

Re: Bug when appending return value of procedure to a string

Post by DontTalkToMe »

freak wrote:Don't believe me? Try the same in C or Java and tell me the result
... wait for it ....
NilsH wrote: Just tried it.
Ach, you beat me to it !
NilsH wrote: Probably it's a just very bad idea to modify a variable within a function that is called in an expression that uses the same variable.
Maybe it's not a great idea, but the result with the C compiler (C++ also gives the same result, with optimizations on or off) is what you expected and it's different from what pb does.
freak
PureBasic Team
PureBasic Team
Posts: 5929
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Re: Bug when appending return value of procedure to a string

Post by freak »

Guess I have been working on the Java side of things for too long...

Code: Select all

public class Test {
	
	static int a = 1;
	
	public static int b() {
		
		a = 999;
		return 1;
	}

	public static void main(String[] args) {

		a += b();
		System.out.println(a);
	}
}
Result is 2. Now what? :)

Anyway, the expression evaluation order is something that every language has to define for itself and it affects how such code behaves. Some languages explicitly define this one way or the other, others leave it undefined for optimization reasons. Still, it is a design decision and not a bug.

Imagine if it worked the other way around. Somebody could just as easily write a bug report because he expected the current behavior. There is no "right" way to do this.

You already found the only sane way to deal with this:
NilsH wrote:Probably it's a just very bad idea to modify a variable within a function that is called in an expression that uses the same variable.
quidquid Latine dictum sit altum videtur
#NULL
Addict
Addict
Posts: 1440
Joined: Thu Aug 30, 2007 11:54 pm
Location: right here

Re: Bug when appending return value of procedure to a string

Post by #NULL »

just because the c code does something in some way with some compiler, that doesn't say anything.
http://en.cppreference.com/w/cpp/language/eval_order

Undefined behavior

Code: Select all

i = ++i + i++; // undefined behavior
i = i++ + 1; // undefined behavior
i = ++i + 1; // undefined behavior (well-defined in C++11)
++ ++i; // undefined behavior (well-defined in C++11)
f(++i, ++i); // undefined behavior
f(i = -1, i = -1); // undefined behavior

Code: Select all

cout << i << i++; // undefined behavior
a[i] = i++; // undefined behavior
you should just avoid so called 'side effects'. it's just not immediately obvious that this pb shortcut statement has side effects. but now you know it :P
DontTalkToMe
Enthusiast
Enthusiast
Posts: 334
Joined: Mon Feb 04, 2013 5:28 pm

Re: Bug when appending return value of procedure to a string

Post by DontTalkToMe »

I agree, let's drop this and concentrate on the other compiler's and ide's bugs.

Let's forget this, it's fine.

Deal ? :wink:
Post Reply