Debug mode don't do the same thing (Bmax 1.41)

Archives Forums/BlitzMax Bug Reports/Debug mode don't do the same thing (Bmax 1.41)

BlitzProg(Posted 2011) [#1]
Global number = 0
Local table:mytype[8]

Type mytype	
	Function make:mytype()
		number:+1
		Return New mytype
	End Function
End Type

table[number]=mytype.make()
If table[0] Print "ID #0 <= the element was stored here" Else Print "ID #0"
If table[1] Print "ID #1 <= the element was stored here" Else Print "ID #1"


In debug mode, i get the element to be stored in #0, and when not in debug mode, i get it stored in #1! T_T


GfK(Posted 2011) [#2]
I am currently partakjing in some new year merriments and amn slightyl badgered. However, using a globail in a type function is a but untifdy - you're far beter off defining the global in the function itself - which basically does the sae job as a static var.

To cut a long an d incoherent story short, this works:
Local table:mytype[8]

Type mytype	
	Function make:mytype()
		Global number:Int 'this is like a static var
		number:+1
		Return New mytype
	End Function
End Type

table[number]=mytype.make()
If table[0] Print "ID #0 <= the element was stored here" Else Print "ID #0"
If table[1] Print "ID #1 <= the element was stored here" Else Print "ID #1"


I dont knw why your version didnt work. Somebody who isnt drunk will be along shortly to help oiut.


Floyd(Posted 2011) [#3]
So Debug and Release give different results. Which one is "correct"? That's not at all clear. They both look reasonable, depending on your point of view.

table[number]=mytype.make()

To execute this line of code two expressions must be evaluated. The value of number is needed so we know which table element to alter. And mytype.make() must be called get the returned object. The trouble is that this function changes number, so table[number] depends on the order in which the two evaluations are done.

This is similar to another common bug report. People expect that a function call like

f( param1, param2, param3 )

will evaluate the parameter values left-to-right, as we read them. That turns out not to be the case.

BlitzMax, unlike C for example, does not have a formal definition. It makes no promises about such order of evaluation issues. You should not write code which depends on any particular order.


BlitzProg(Posted 2011) [#4]
To make it clear, this is old code. i no longuer code this way, but I decided to re-use a piece of code that was working this way from my archives and simply ended up crashing on release mode. :)

Even though you shouldn't code that way, I believe it's still something to be looked into rather than be "avoided" (what do you thing game testers do, anyway?)

The real bug report here is the fact debug and release behaves differently, which is quite unconvenient for programming. In the program i used this piece of code, I went for release executing, ended up with memory access violation, and when trying the debug version to find out the source of the error, everything was doing fine... :)

Type mytype
	Field test:String = "hey, it works fine! Try the Release version! :D"
End Type

Global n=0
Global table:mytype[2]

Function set:mytype() 
	n:+1
	Return New mytype
End Function

table[n]=set()
Print table[0].test


Last edited 2011


ziggy(Posted 2011) [#5]
Wow, that one is fantastic! It seems debug mode is catching the array index before evaluating the result of the operation in the assignment, while in release mode it's done properly. Don't know why, it looks like a genuine bug to me.


Floyd(Posted 2011) [#6]
debug mode is catching the array index before evaluating the result ... in release mode it's done properly

This may be a bug, in that Release and Debug behave differently. But I still say it is not clear which way is the proper one.

table[number]=mytype.make() can be interpreted in two reasonable ways:

1. Read it left-to-right, the way we read English. This would involve evaluating number and then mytype.make(). This is the Debug style.

2. Look at it as a statement of the form y = f(). This suggests we evaluate f(), and then store the result in y. We don't need to think about, or even look at, y until after f() is called. This is Release style.

GG's test code implies that he thinks #1 is correct, otherwise the array index goes out of bounds when we try to fill the table[] array. Ziggy thinks #2 is the proper way.

I'm not sure which way I vote. My first thought is that #2 is right. We must know what to assign before deciding where to assign it. But that also has the undesireable side effect that table[number] is "touched" twice, when number is incremented and when the assignment is done.


BlitzProg(Posted 2011) [#7]
I tried in blitzplus and it seems that it always goes in zero. Maybe it could be helpful in knowing which version to choose. :)
Global number = 0
Dim table.mytype(8)

Type mytype	
	
End Type

Function make.mytype()
	number=number+1
	Return New mytype
End Function

table(number)=make()
If Not (table(0)=Null) Print "ID #0 <= the element was stored here" Else Print "ID #0"
If Not (table(1)=Null) Print "ID #1 <= the element was stored here" Else Print "ID #1"