views:

85

answers:

3
function testFunc(val1:int, val2:int, val3:int):int {
    var returnVal:int = 0;
    return returnVal;
}

var val:int = testFunc(1, 2, 3);

causes

locals: Main int int int * 
4:dup VerifyError: Error #1023: Stack overflow occurred.
A: 

Thank you for pointing this fact out. Anyways here is what I realize.

A function in AS3 is defined as

function apply(thisArg:*, argArray:*):*

i.e any user function will be mapped into adobe defined Function.apply as above. I guess this is something similar to the environment variables in c. The first argument can be used to send the length of the Array of arguments followed by the Array itself.

So this basically means, if you wish to use the above function call you can define your function as

function testFunc(...args):int {

val1:int = args[0];
val2:int = args[1];
val3:int = args[2];

var returnVal:int = 0;
return returnVal;

}

var val:int = testFunc(1, 2, 3);

I did not really find anything around Google though. Which lead me to go to aobe's page itself. Anyways glad that I learned something new.

Edit: Please do look over the function definition here : http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/Function.html

loxxy
This does not explain the stack overflow error
Amarghosh
Of course it does, doesn't it?....It shows that as3 is prepared to take the two variables in a single stack. When it realizes that there is an array coming then only will it allocate a new stack else throws error.
loxxy
@loxxy. No, it doesn't. And your answer and your comments don't make much sense. The player does not 'allocate a new stack when it realizes that there is an array coming'. Function apply has nothing to do here, either. "i.e any user function will be mapped into adobe defined Function.apply as above". Where did you take this from? Function apply is a high level construct; how the compiler translates that call or any other call to byte code and how the VM executes it, is a different matter.
Juan Pablo Califano
loxxy
+1  A: 

This page discusses a similar stack overflow issue. It seems adding a trace somewhere in the function will fix it.

It's a known bug

Amarghosh
No seriously, trace can never ever remove a bug on its own. Trace is simply a developers tool to let you debug or rather trace the bug as the name suggests. By the way I think its no bug, we are trying to implement a feature in the way we understand rather than what they specify.
loxxy
Then why have I made many multiple parameter functions in the past that didn't cause such an error? This appears to be a weird case where it does trigger stack overflow, which would imply that it's not intended.
VWD
Yes this is a bug and trace indeed fixes it.
Allan
@Allan Thanks for confirming it.
Amarghosh
@loxxy well I would not say that. If you look at the abc bytecode you can see that trace causes the string value of the trace function to be pushed onto the stack as well as a couple of other operations to occur. Since this is a bug in the player itself then certainly by changing the stack can have an affect (and indeed does).
Allan
@Amarghosh well actually I had not encountered it before but really it is a simple bit of code and I was pretty stumped by the bug. The fact that you also were unsure and the link you found makes me 99.9% certain hehe
Allan
oh and yes I tested it out on a machine at work and home with your fix just to be sure (and had a look at the ABC bytecode)
Allan
A: 

Yes it's a bug player, another workaround will be to cast your result to int, so the instruction generated by the compiler will not be the same:

in the first case:

function testFunc(val1:int, val2:int, val3:int):int {
    var returnVal:int = 0;
    return returnVal;
}

the compiler generate something like that: Note that there is nothing wrong with the code generated

getlocal 0
pushscope 
pushbyte 0      // stack = 0
dup             // stack = 0 0
setlocal 4      // set returnVal with value on stack, stack = 0
returnvalue     // return the value left on the stack i.e. 0, stack=empty

and for the workaround:

function testFunc(val1:int, val2:int, val3:int):int {
    var returnVal:int = 0;
    return int(returnVal);
}

the code generated is

getlocal 0
pushscope 
pushbyte 0           // stack = 0
setlocal 4           // set returnValue with the value on the stack, stack=empty
findpropstrict int   // push on stack the object holding the int property, stack=object
getlocal 4           // push on stack returnVal, stack=object 0
callproperty int(param count:1) // call the int property , stack=0
returnvalue          // return the value left on stack i.e 0, stack=empty
Patrick