This is worth knowing...

BlitzMax Forums/BlitzMax Programming/This is worth knowing...

Grey Alien(Posted 2006) [#1]
OK, I know this isn't the best OOP code. But basically if a method of a type calls an external function that kills the global instance of the type, the type won't get killed until the method exits. This can be seen by running the following code. The print line still works. However, uncomment t.More() and run in debug mode and you will get a null object error.

Strict
Type TTest
	Method Bang()
		KillTest()
		Print "hello"
	End Method
	
	Method More()
		Print "more"
	End Method
End Type

Global t:TTest = New TTest

t.Bang()
't.more() 'uncomment this line

Function KillTest()
	t = Null
End Function

Does anyone know if the garbage collection code *always* works like this in this sort of situation of could it free up the type before the print occurs, or could it leave the type hanging around for a bit longer so t.more() works?

Thanks.


Grey Alien(Posted 2006) [#2]
OK I just tried added a nested method that destroys the instance and it shows that the type isn't killed until the original method is exited, not just the nested one, which is to be expected:

Strict
Type TTest
	Method Bang()
		Nested()
		Print "nested"
	End Method

	Method Nested()
		KillTest()
		Print "hello"
	End Method
		
	Method More()
		Print "more"
	End Method
End Type

Global t:TTest = New TTest

t.Bang()
't.more() 'uncomment this line

Function KillTest()
	t = Null
End Function



Dreamora(Posted 2006) [#3]
Sure it isn't exited, would be the worst thing that could happen in that situation!

Thats expected behavior as the object is freed when it isn't referenced anymore and as long as some code on the object is running, the object is still referenced by the calling system to execute the method it is actually in.


Grey Alien(Posted 2006) [#4]
yeah that's what I thought, the code shouldn't exit a function to return to a method in unallocated memory, ouch! But you might want a situation where the remaining code isn't run. To do that you could set a flag I guess, or just change the code totally so it isn't freed from within a method.


Dreamora(Posted 2006) [#5]
If you don't want the remaining code to be run, this is still no solution and only guarantees you real trouble, as it will result in a access violation or blue screen.

If the remaining code shall not run, there are 2 possibilities:

- Test each block of code with if to see if it shall be executed.
- Check for a break condition and return in case it is needed.


H&K(Posted 2006) [#6]
In the second post, can you call more from bang?


Dreamora(Posted 2006) [#7]
Sure, at that point, the object still exists as it is running the method.


Grey Alien(Posted 2006) [#8]
Test each block of code with if to see if it shall be executed.
That's waht I mean when I said:
To do that you could set a flag I guess
Anyway, I don't actually need to do that I was just being hypothetical.


Dreamora(Posted 2006) [#9]
There would be another potential way of doing it, but other experienced users will hit me for telling you this way because its not meant to be missused for lazyness:

Try - Catch - throw

With that you could test all executions on the "highest" level and when you want the object to be destroyed the same moment due to some reason, you could simply throw the needed signal and return when you catch that to leave the "highest level method" within the object which will take care that it isn't referenced anymore.

but forget that I mentioned this method, ok? ;-)


Grey Alien(Posted 2006) [#10]
ah yes that's a bit naughty. For my Delphi apps I use Try Except all the time, but haven't used it in my games so far as I expect everything to work :-)


Red Ocktober(Posted 2006) [#11]
i know some people who wrap all their code in try/except/catch blocks...

--Mike


Jim Teeuwen(Posted 2006) [#12]
bad, bad and bad again :p

thats like using that ancient 'On Error Resume Next' in Visual basic in every function :p

And then ppl wonder why they keep getting totally unexplainable errors which are a nightmare to debug :p


WendellM(Posted 2006) [#13]
OK, I know this isn't the best OOP code.

That's an understatement! ;) What were you trying to do, get your program to lobotomize itself with that stunt? LOL

I don't actually need to do that I was just being hypothetical.

You had me worried for a moment... :) But testing the robustness of the language/compiler is a good thing, so well done.


Grey Alien(Posted 2006) [#14]
But testing the robustness of the language/compiler is a good thing, so well done
thanks ;-)


Curtastic(Posted 2006) [#15]

But basically if a method of a type calls an external function that kills the global instance of the type, the type won't get killed until the method exits.


Don't think of it as something you should memorize about how blitz works on killing your type instances. An instance is dead, to you, when you have no way of accessing it. Thats all that matters. Blitz will go ahead and internally clear the RAM of a dead instance whenever it wants to it doesn't really matter.

Inside the method you can still access the instance with Self.whatever, even after t is set to null. That's how you are still able to use the instance. Once the function exits, you have no way of accessing the type. it may or may not exist in ram, to you its just gone because you have no variable in your code that lets you get to it.

sorry I was babbling. this stuff took me a while to figure out.