开发者

FIXED: Deleted array value still showing up on foreach loop in AS3 (bug in flash?)

UPDATE 2011.09.13 This bug has been resolved by Adobe. The example code below now exhibits the correct behavior. Original question is below.

It took me many hours to narrow down a problem in some code to this reproducible error, which seems to me like a bug in AVM2. Can anyone shed light on why this is occurring or how to fix it?

When the value at index 1 is deleted and a value is subsequently set at index 0, the non-existent (undefined) value at index 1 will now show up in a foreach loop. I have only been able to produce this outcome with index 1 and 0 (not any other n and n-1).

Run this code:

package 
{
import flash.display.Sprite;
public class Main extends Sprite 
{
    public function Main():void 
    {
        var bar : Array = new Array(6);
        out(bar);

        //proper behavior
        trace("bar[1] = 1", bar[1] = 1);
        out(bar);

        //proper behavior
        trace("delete bar[1]", delete bar[1]);
        out(bar);

        //proper behavior
        trace("bar[4] = 4", bar[4] = 4);
        out(bar);

        //for each loop will now iterate over the undefined position at index 1
        trace("bar[0] = 0", bar[0] = 0);
        out(bar);

        trace("bar[3] = 3", bar[3] = 3);
        out(bar);
    }

    private function out(bar:Array):void
    {
        trace(bar);
        for each(var i : * in 开发者_JS百科bar)
        {
            trace(i);
        }
    }
}

}

It will give this output:

,,,,,
bar[1] = 1 1
,1,,,,
1
delete bar[1] true
,,,,,
bar[4] = 4 4
,,,,4,
4
bar[0] = 0 0
0,,,,4,
0
undefined
4
bar[3] = 3 3
0,,,3,4,
0
undefined
4
3

EDIT: See answer for likely cause of the bug. Unable to find a fix. My solution was to code a special case where if index 0 is being set and index 1 does not exist, delete index 1 after setting index 0. Not exactly an elegant solution :\


It looks like you're running in to a bug that seems to happen when AS3 arrays are split into a dense array part and a "rest" hashtable part.

It's been reported as an "Actionscript Core Language" bug to Adobe here: FP-3477

There's also a couple of blog-post links there to other developers that have run into the (probably) same issue.

Although your example code doesn't re-insert the same object, there might be related issues to how the VM is optimizing low-range literal numbers (often as shared, constant 'objects')


While clearly a bug, I'd say it has more to do with the fact that the array values are in some form of weird state when initialized as var bar : Array = new Array(6);, they should be iterated over to begin with as far as I can see.

I actually never use delete bar[1] to get rid of a value in an array, I always go for bar.splice(1, 1)*, when doing this all unset indices will begin to trace as undefined, so there's clearly something strange going on.

While I suspect you're not really looking for a workaround, I'd just try to live with the potentially iterated empty positions, either handling them as you encounter them or by doing a for (var i:int = 0; i < bar.length; i++) style loop instead.

If you don't need the array-type behaviours, using Object could work as well, it doesn't seem to have this issue.

* this is just by preference, no real reason.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜