This is worth knowing...
BlitzMax Forums/BlitzMax Programming/This is worth knowing...
| ||
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. |
| ||
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 |
| ||
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. |
| ||
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. |
| ||
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. |
| ||
In the second post, can you call more from bang? |
| ||
Sure, at that point, the object still exists as it is running the method. |
| ||
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. |
| ||
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? ;-) |
| ||
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 :-) |
| ||
i know some people who wrap all their code in try/except/catch blocks... --Mike |
| ||
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 |
| ||
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. |
| ||
But testing the robustness of the language/compiler is a good thing, so well done thanks ;-) |
| ||
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. |