GCCollect wont collect if method called

BlitzMax Forums/BlitzMax Programming/GCCollect wont collect if method called

gman(Posted 2006) [#1]
in this simple example, if the method on tObj1 is called, the GC will not collect. if its not called, it will. there is nothing in the method to increase the reference count so calling the method should not affect GCCollect().
SuperStrict
Framework BRL.Basic

Type tObject
	Method A:String()
		Return "tObject.A()"
	EndMethod
	
	Method Delete()
		Print "tObject gone!"
	EndMethod
EndType

GCCollect()
Print GCMemAlloced()

Local tObj1:tObject=New tObject

GCCollect()
Print GCMemAlloced()

' with this line running, the object is not collected.
' comment this line and it works.
Print tObj1.A()

tObj1=Null

GCCollect() ' if tObj1.A() was called the object doesnt collect
Print GCMemAlloced()



gman(Posted 2006) [#2]
this is interesting. if i add the code:
Local objptr:Byte Ptr=Byte Ptr(tObj1)
objptr=Null

anywhere after tObj1 is created, the GC works as expected.


DStastny(Posted 2006) [#3]
I dont think this is a bug but more a situation based upon the state of the Call Stack and the CPU Registers.

Local variable Objects are not reference counted so as far as the GC is concerned just setting it to NULL wont force clean up until the Scope from which the varible was declared is popped off stack. That will guaranetee it gets cleaned up next time GCCollect is called.

In context of stact frame it may or may not get cleaned up as you found by adding the additonal code. Due to the way the local stack frame and registers might be effected.

When you declare local varibles inline like your example, the variable exists in the stack context of that function since all a BMAX application is is a function called by the startup code all local variables declared are in scope of that function on the stack.

Calling other functions GCCollect Pushes the resisters on stack so when Garbage Collector scans the stack it might still think the local variabls are alive, as its still on the stack or in a register. Hense the seemingly random behavior.

If you want to see what I mean change the variable to global in your example and what happens.

Play with this example
SuperStrict
Framework BRL.Basic


Type tObject
	Method A:String()
		Return "tObject.A()"
	EndMethod
	
	Method Delete()
		Print "tObject gone!"
	EndMethod
EndType

GCCollect()
Doit()
GCCollect()
End
Function DoIt()
	Print "In Doit"
	Local tObj1:tObject=New tObject
	GCCollect()	' Comment out this line to see changed behavior
	Print tObj1.A()
	tObj1=Null
	GCCollect() 
	Print "Exit Doit"
End Function 


It can be confusing but the GC works just dont assume setting or rely on setting varibable to NULL and calling GCCollect() will imidiately clean up. It will be eventually, but you can rely on it.

Doug Stastny


H&K(Posted 2006) [#4]
I had thought that we had been told that in a situation like this the local instance would mean that the object isnt collected straight away.

That is, that in a "Test" situation the object appears to still exist, but after a few calls to other functions and stuff, (ie real application), the object would be collected?


gman(Posted 2006) [#5]
@Doug - thx for the inside info. i figured telling the GC to collect would... well collect any released objects at the time its called but it looks like certain situations still cause a delay. i guess the problem here is (me in) that GCCollect() doesnt quite have the functionality i was expecting it to have. again, thank you for the clarification. it is very much appreciated.