Destructors / Memory Leaks / Garbarge Collection... you know how this goes



  • Right i will get straight to he point, i have looked around before asking this, googled away and all that but i am slightly confused.

    I come from the pascal/Delphi world and in that world everything that is created must be free'd (FreeAndNil to be exact) inside of a destructor which is inherited then overrided from the base object TObject.

    Now its been a while since i looked into haxe and haxeflixel but the last time i did the tutorial on the site mentioned a class (FlxDestroyUtil i think) which was being used in the destructor (i think it said "everything that is created must be destroyed"), now i am looking at the tutorial and i downloaded the latest version of haxeflixel and cannot see the overridden destructor method in the playstate class... where has it gone? (i noticed that there is still a destructor in the flxState class that playstate is inheriting from)

    I am also wondering what is the deal with garbage collection in Haxe, i have heard (the openfl people) whispers and a mention here and there on a forum or two that there is a GC and that it is reference counting objects and cleans them up when they become null or out of scope similarly to Java and c# but if that is the case why do you still have this FlxDestroyUtil object which is being used to destroy objects when your finished with them.

    Along time ago at university i learned Java and in Java just like in haxe i see code like this "FlxG.switchState(new PlayState());" which is all fine and dandy in c# and Java but a big no no in Delphi or C++ unless the object itself has some sort of reference counter on it or has some sort of self destruct code as you no longer have a reference to it and thus will end up with a memory leak. I can except if there is a GC that when building to a CPP target that it is just "magic" that haxe got all of its memory cleaning correct in the right places.

    importantly i really need to know how garbage collection and freeing memory works in haxe because if i make a game for ios and it gets reviewed by apple there is no way they will let some memory leaking garbage (one would hope) anywhere near the app store.. not only that though i try to make the best software i can and i take pride in what i develop. Leaky memory is very bad.

    So given all of this can someone tell me, what is going on?



  • IIRC I was told that, unless you have circular refs, nowadays HaxeFlixel handles everything for you by default whenever you switch states. Maybe someone can add more detail to that...:)



  • @IBwWG Some details would be nice, looking again through google it would seem that GC depends on the platform you would be building to, that would make me believe that for a CPP target like windows you would have to clean your own memory but not for a HTML5 target for example, i hope we get some answers.

    Thanks



  • Remember that everything is constructed inside a FlxGame object, so, you can add a "new" state, but basically, what you are adding is a fancy group, which will be handled internally by FlxGame class, and indeed, as @IBwWG pointed out, memory clearing will be done automatically.

    Anyways, is a good idea to take into account memory. FlxGame will take care of this for Flx objects, but will not work for everything. Example?

    public static var instance:StateGameplay;
    
    	override public function create():Void
    	{
    		if (instance == null)
    		instance = this;
    
    ...
    

    If you don't null the object on Destroy(), like:

    if (instance != null)
    {
           instance = null;
    }
    

    ... you will always have a reference of the state, in memory.

    One of the other tips that I found super useful is manually triggering of the garbage collector. You can do this by simply doing:

    System.gc();
    
    #if cpp
        cpp.vm.Gc.run(true);
        cpp.vm.Gc.compact();
    #end
    

    And for web targets, is always good to remember that, the more tiny, the better, and that applies for everything, even sounds. Also, using Atlases is a great idea to save memory, by referencing a single image, instead of tons of differents ones. That's all I got now :)


  • administrators

    @neal Every Haxe target is garbage-collected. CPP is a special case in that it doesn't have native GC, that's why the hxcpp runtime implements it.

    destroy() (IFlxDestroyable) functions in Flixel are not technically "destructors", think of them more like dipose() ( IDisposable) in C#. You can use them to do some manual cleanup. Sometimes they are used to explicitly null object references to help GC along, but there's some debate over whether this really helps.

    Either way, as long as you don't hold onto object references longer than necessary, you should be fine.



  • @Claudio-Ficara Thanks for providing an example. If I may confirm something, in your example it's because instance is static that's is a problem, right?

    For another example, I have a substate, which needs to access, in some of its functions, a few public variables that belong to the parent state. So in my substate's create() I have

    specialStateRef = cast(_parentState, SpecialFlxState);
    

    ...referring to a private, non-static variable of the substate, specialStateRef. In this case, one doesn't need to nullify it in the substate's destroy() because it's not static, right? (My thinking is, where would the reference specialStateRef be held in memory once the substate instance itself is no longer in memory?)



  • @IBwWG said in Destructors / Memory Leaks / Garbarge Collection... you know how this goes:

    @Claudio-Ficara Thanks for providing an example. If I may confirm something, in your example it's because instance is static that's is a problem, right?

    For another example, I have a substate, which needs to access, in some of its functions, a few public variables that belong to the parent state. So in my substate's create() I have

    specialStateRef = cast(_parentState, SpecialFlxState);
    

    ...referring to a private, non-static variable of the substate, specialStateRef. In this case, one doesn't need to nullify it in the substate's destroy() because it's not static, right? (My thinking is, where would the reference specialStateRef be held in memory once the substate instance itself is no longer in memory?)

    The example that I provided is just to clarify that there could be cases where one can indeed, override the way HaxeFlixel handles memory. It could happen, I mean, HaxeFlixel can't take into account every little piece of code you add :) - The problem might be the static access, of course, and as you pointed out, there are other ways to access another states, better ways of course.

    As for what you mention, I'm not sure. You can easily find out by doing a trace(specialStateRef ); outside your working area, and it must be null. If not, you have a problem.

    As for memory leak goes, I can't say that I had a problem with that, but as @IBwWG pointed out, there could be cases where you can indeed, break things, so OP should be aware of that.

    And since is topic related, I wrote on this very forums, some sort of post about memory and general optimizations that you can do, that I found useful. It was for HTML5, but it surely can be applied to any target. In your case OP, I'd take great benefit of the tips about FlxGroups, recycle() revive() and creating everything you would need, at create()



  • @Claudio-Ficara What's my working area? I would think the class, since it's a private class variable, but outside the class such a statement wouldn't even compile. That's why I think it only applies to static variables, or perhaps variables you pass between states (or keep "alive" in some other way.)

    As for "better ways of course" I would love to be educated on this point but maybe I should open a new thread for that. :)


Log in to reply