In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

Closure Memory Leak

Example show that don't nulled variables hold instances for a long time, and maybe forever.

So good advice - to null local variable if you use closure.

## UPDATE

Memory Leaks can be fit with System.gc(). Look here:
http://wonderfl.net/c/mb50 - Closure Memory Leak with System.gc().

So them will be removed in mark/sweep phase http://www.adobe.com/devnet/actionscript/learning/as3-fundamentals/garbage-collection.html but anyway it's performance cost phase and better to avoid using of closures.
Get Adobe Flash player
by hyzhaka 19 Apr 2013
/**
 * Copyright hyzhaka ( http://wonderfl.net/user/hyzhaka )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/iWFL
 */

package {
    import flash.text.TextField;
    import flash.utils.setTimeout;
    import flash.utils.Dictionary;
    import flash.display.Sprite;
    import com.actionscriptbible.Example;
     
    /**
    * Example show that don't nulled variables hold instances for a long time, and maybe forever.
    *
    * So good advice - to null local variable if you use closure
    *
    */
    public class ClosureLeaks extends Example {
        private var _pool:Dictionary = new Dictionary(true);
        
        public function ClosureLeaks() {
            buildClosureTests(3, 200);
            
            logTestInstancesRightNow();
            setTimeout(logTestInstancesBeforeFree, 100);
            setTimeout(logTestInstancesAfterFree, 300);
            
            setTimeout(logClosureInstanceBeforeFree, 100);
            setTimeout(logClosureInstanceAfterFree, 300);
        }
        
        /**
         * Create some instance of test class, and execute closure test in each
         */
        private function buildClosureTests(i:int, freeTime:int):void {
            while(--i>=0) {
                var instance:ClosureLeaksTest = new ClosureLeaksTest(i.toString(), freeTime).execute();
                _pool[instance] = true;
            }            
            
            _pool[new ClosureLeaksTest("don't execute method with clouse", freeTime)] = true;
        }
        
        /**
         * Show state of closure tests before free in closure test
         */
        private function logTestInstancesRightNow():void {
            trace("\n## Test Instances right now");
            logPool(_pool);            
        }
        
        /**
         * Show state of closure tests before free in closure test
         */
        private function logTestInstancesBeforeFree():void {
            trace("\n## Test Instances before free");
            logPool(_pool);            
        }
        
        /**
         * Show state of closure tests after free in closure test
         */
        private function logTestInstancesAfterFree():void {
            trace("\n## Test Instances after free");
            logPool(_pool);            
        }
        
        private function logClosureInstanceBeforeFree():void {
            trace("\n## Before free instance");
            logPool(ClosureLeaksTest._pool);
        }  
        
        private function logClosureInstanceAfterFree():void {
            trace("\n## After free instance");
            logPool(ClosureLeaksTest._pool);
        }  
        
        private function logPool(pool:Dictionary):void {
            for(var instanceAfter:* in pool) {
                trace("* instance: '", instanceAfter.name, "'");
            }            
        }
    }    
}
import flash.events.TimerEvent;
import flash.utils.Timer;

import flash.text.TextField;
import flash.utils.setTimeout;
import flash.utils.Dictionary;
import flash.display.Sprite;

/**
* Execute test with closure function
*
*/
class ClosureLeaksTest{
    public static var _pool:Dictionary = new Dictionary(true);
    
    private var _name:String;
    private var _freeTime:int;
    
    public function ClosureLeaksTest(name:String, freeTime:int) {
        _name = name;
        _freeTime = freeTime;
    }
        
    /**
    * Execute clouse test
    */
    public function execute():ClosureLeaksTest {        
        var nulledInstance:Object = {name:"nulled instance of " + _name};
        var doenstNulledInstance:Object = {name:"doenst nulled instance of " + _name};
        
        _pool[nulledInstance] = true;
        _pool[doenstNulledInstance] = true;
        
        //Here is closure!
        var timer:Timer = new Timer(_freeTime, 1);
        timer.addEventListener(TimerEvent.TIMER, function():void {
            //hack to remove instance from closure scope
            nulledInstance = null;
        });
        
        timer.start();
        
        return this;
    }  
    
    public function get name():String {
        return _name;        
    }
}