AS3 passing a function as a parameter creates memory leaks

I have a function that takes another function as a parameter. Something like that:

public function onHits(target : Shape, callback : Function) : void 

I use it by passing a member function as a parameter, which should be called whenever the passed object hits. A function is called multiple frames. Therefore, it is used:

 //code... CollisionManager.onHits(myShape, onHitCB); //code... 

Function on hit:

 public function onHitCB(hitObject : *) : void { //removed all code to test this problem } 

When I do this, I get a memory leak. I highlighted the problem for this onHits method and commented on everything else. onHits is an empty method without code inside it, onHitCB is also empty. If I comment on the onHits call, there is no memory leak, and if I pass null instead of onHitCB, there will be no memory leak.

So, this is clear when I pass onHitCB as a parameter, which is the problem. Therefore, I thought that this could be because Flash allocates some memory to create the Function pointer and does not release it, but I call System.gc () every frame in debug mode, and the leak still exists. This would mean that it is either an error in the SDK, or I am not doing anything right.

I found a strange workaround by storing a variable that points to the function that I assign in the constructor of my object:

 private var func : Function; public function MyObject() { func = onHitCB; } 

and this will clear the memory leak even if I still pass onHitCB as a parameter . Does this mean that this is not a getter function to get onHitCB, but something else that causes a memory leak?

I am very confused. How can this cause a memory leak:

 public function MyObject() { } public function update() : void { CollisionManager.onHits(myShape, onHitCB);//empty function } public function onHitCB(hitObject : *) : void { //removed all code to test this problem } 

but not that?

 private var func : Function; public function MyObject() { func = onHitCB; } public function update() : void { CollisionManager.onHits(myShape, onHitCB);//empty function } public function onHitCB(hitObject : *) : void { //removed all code to test this problem } 

and is there any way not to do this workaround?

+8
flash memory-leaks actionscript-3 function-pointers
source share
4 answers

[...] related methods are automatically created when the method is passed as a parameter. Related methods ensure that this keyword always refers to the object or class in which the method is defined. A source

It seems that creating a method reference does not use a simple getter. A new method closure object is created. So your assumption is correct.

I wonder why the links are not cached for each instance and why they are not collected with garbage. Better to avoid creating multiple links. If you access the method only once, this is exactly what I would do when I would have to use this method in several places, so most of the time I would not call it a workaround, but good DRY practice. In your example, this of course makes sense, assuming the method reference will use a simple getter.

+5
source share

For more information on what does and does not cause memory leaks when using functional methods, check out http://www.developria.com/2010/12/functional-actionscript-part-1.html . Also, keep in mind that using static methods like this is really bad practice (http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/), and you are just starting to face many problems caused by using this method. It seems that you are already quite early in your project, that you are not completely committed to this path, so you can look at other ways to program this.

+1
source share

I am not sure if your code is in the onHits function, but if it does not require additional time to complete in another loop. then I recommend you do like this:

 static public function onHits(target : Shape) : * { // do what you need // return the hitObject; return hitObject; } 

and

 public function update() : void { // parse the object direc to to the function. onHitCB ( CollisionManager.onHits(myShape) ); } public function onHitCB(hitObject : *) : void { if ( hitObject == null ) return; // if it not null then do all your calculations. //removed all code to test this problem } 
0
source share

And that’s why we don’t do this kind of thing in OOP style programming.
It’s best to do it right and add a callback to the CollisionManager class.
The reason it can be GCed when you save a local link is because the function never loses scope because this var contains the link. <br / "> As soon as something loses the sphere, GC it becomes practically impossible.

Try this and see how you lose the area.

 private var somevar:String = 'somevar with a string'; public function MyObject() { } public function update() : void { CollisionManager.onHits(myShape, onHitCB);//empty function } public function onHitCB(hitObject : *) : void { trace(this.somevar) // scope should be lost at this point and somevar should be null or toss an error. } 
-one
source share

All Articles