Can't concat empty arrays of extern type

Archives Forums/BlitzMax Bug Reports/Can't concat empty arrays of extern type

Yasha(Posted 2015) [#1]
Example of the problem:

SuperStrict

Type foo
	Field a:Int, b:Int
End Type

Extern
Type bar
	Field a:Int, b:Int
End Type
Function newBar:bar(sz:Int) = "bbMemAlloc"
End Extern

Local a:foo[] = Null
a :+ [New foo, New foo, New foo]
a :+ New foo[3]

Local b:bar[] = Null
b :+ [newBar(16), newBar(16), newBar(16)]
'b :+ New bar[3]	'boom

Local c:bar[] = New bar[3]	'not a problem
'c :+ b		'boom

Print "done."


Uncomment either of the lines that try to add to b or c, and the program doesn't even raise an exception in debug mode - it just dies.

As you can see from c, actually creating an empty array of extern objects doesn't seem to be the problem, and using an auto-array (which I guess is equivalent to creating and then immediately populating it) works well too. But trying to add an array of nulls to anything is a no go.


Yasha(Posted 2015) [#2]
A related problem:

SuperStrict

Type foo
	Field a:Int, b:Int
End Type

Extern
Type bar
	Field f:foo
End Type
Function newBar:bar(sz:Int) = "bbMemAlloc"
End Extern

Local b:bar = newBar(16)
b.f = New foo

Print "done."


Trying to store a BlitzMax object in a field of an extern object also causes the program to die without warning.

It's reasonable that this one might not be allowed, but the compiler doesn't actually object to it.


Yasha(Posted 2015) [#3]
Yipes, even when it works it doesn't work. Even worse example:

SuperStrict

Extern
Type foo
	Field b:bar
End Type
Type bar
	Field a:Int, b:Int
End Type
Function newFoo:foo(sz:Int) = "bbMemAlloc"
Function newBar:bar(sz:Int) = "bbMemAlloc"
End Extern

Local arr:foo[] = Null

Local f:foo = newFoo(16)
f.b = newBar(16)

Print Hex(Int(Byte Ptr(f.b)))
arr :+ [f]
Print Hex(Int(Byte Ptr(f.b)))

Print "done."


This does something worse than crash: it corrupts the data in the objects!

I've managed to track the cause of this new behaviour down, at least - bbArrayConcat contains this line:

if( type[0]==':' || type[0]=='$' || type[0]=='[' ){


...to determine whether to increment the reference counts of its elements (i.e. if they're objects or not). The names of extern types are stored with the ':' prefix in the assembly, so they're incorrectly detected as BlitzMax objects by this code, and it attempts to BBRETAIN them.

This is a critical bug, although again, it's not clear whether the problem is with the implementation of arrays, or with the fact that the compiler allows one to write this code at all.