Weird invalid access error



  • I'm working on a project that requires me to test if two spriteGroups are overlapping. I'm doing so with this code:

    if (puyo != null)
    {
    	if (puyo.overlaps(puyoB)) 
    	{
    		return true;
    	}
    }
    return false;
    

    puyo and puyoB extend FlxSpriteGroup

    when running I will randomly get this error stack (it doesn't happen every time these lines run and I'm yet to find any pattern):

    Invalid field access : length
    Called from flixel/group/FlxSpriteGroup.hx line 749
    Called from flixel/FlxObject.hx line 737
    Called from flixel/FlxObject.hx line 754
    Called from flixel/group/FlxGroup.hx line 36
    Called from flixel/FlxObject.hx line 723
    

    during my debug steps I've discovered that if I use a try catch block to probe into the puyo being tested with this code:

    if (puyo != null)
    {
    	try
    	{
    		if (puyo.overlaps(puyoB))
    		{
    			return true;
    		}
    	}
    	catch (err:Dynamic)
    	{
    		trace("puyo is null: " + (puyo == null));   
    		trace("puyo length: " + puyo.length);
    	}
    }
    return false;
    

    I get the following error stack:

    BattleBoard.hx:395: puyo is null: false
    AL lib: (EE) alc_cleanup: 1 device not closed
    Invalid field access : length
    Called from gameplay/battle/BattleBoard.hx line 396 "<< this is the trace puyo length line"
    

    I get this error both when trying to access FlxSpriteGroup members and when trying to access members introduced in my extension of it.

    The problem seems to be that I'm getting an invalid access on a non-null value, which I thought haxe's strict typing should make impossible. If anyone has any idea whats going on I would be very grateful for the help.


  • administrators

    Could you share some of the surrounding code? Where does puyo come from exactly? Is there any point where you cast it or it's Dynamic?

    There's a chance you get "invalid field access" because the object does indeed not have a length field, because it doesn't have the type you think it does (if you subverted the type system with cast or similar, that is).



  • puyo is an instance of an extension of FlxSpriteGroup (called Puyo). It's never cast to, or from, and it is not Dynamic.

    this code is the complete function in question, puyo is the only parameter (I've changed the body of the catch statement):

    for (puyoB in AllPuyo)
    {
    	if (puyo != null)
    	{
    		try
    		{
    			if (puyo.overlaps(puyoB))
    			{
    				return true;
    			}
    		}
    		catch (err:Dynamic)
    		{
    			FallingPuyo.remove(puyo);
    		}
    	}
    }
    return false;
    

    with further testing I've found that it only triggers an error sometimes when called from a particular line. that line is part of a for loop that calls this function with puyo as every member of the array FallingPuyo. This array is only ever added to by the Puyo constructor pushing "this" onto it (meaning only actual Puyo can join the array in theory).

    the addition to the function that just removes the offending objects seems to fix the issue with no weird side effects but ideally I'd like to never add the janky objects to the array in the first place. Is there any way for me to check the underling "true" type of an object? or get a list of it's members so I can figure out where it might be coming from?

    thanks for your help.


  • administrators

    @grimms767 There's Type.getClass() and Type.getClassName(), which can be used together:

    var className = Type.getClassName(Type.getClass(object));
    

    For a list of fields, you could use Reflect.fields().

    That said, I would try to avoid using these for the final code (although they may be useful for debugging).



  • @gama11 said in Weird invalid access error:

    Reflect.fields()

    so I've used reflect on the offending object and I'm now more confused. The fields that were given are:

    drag,_point,maxAngular,last,mass,antialiasing,Board,path,color,origin,animation,elasticity,_facingHorizontalMult,GroupV2,_flashRect2,flixelType,angularVelocity,dirty,allowCollisions,numFrames,_flashRect,wasTouching,offset,frameHeight,DebugPuyoNo,facing,_halfSize,Frozen,framePixels,useColorTransform,graphic,_frameGraphic,scale,Colour,_flashPointZero,_skipTransformChildren,health,_rect,x,y,ID,touching,_frame,flipX,flipY,_facingFlip,_facingVerticalMult,collisonXDrag,moves,useFramePixels,maxVelocity,active,_sprites,group,angularAcceleration,acceleration,bakedRotationAngle,angularDrag,_cameras,shader,velocity,_cosAngle,alive,alpha,angle,visible,immovable,_matrix,DebugGroupNo,colorTransform,frameWidth,_angleChanged,blend,_flashPoint,_sinAngle,scrollFactor,pixelPerfectPosition,exists
    

    These are all fields that puyo should have and some of them are only contained in puyo (like GroupV2 and Frozen) however it is missing a bunch of fields (like members and length and Filter) that all the other puyo have. Both the present and missing fields are from both the parent classes and the extension (Puyo). If I print the class of the object I get the expected (Puyo). Do you have any idea why this could be? and just to be clear does the Type.getClass function return the type of the object itself or just the type of the variable storing it?


  • administrators

    Do you have any idea why this could be?

    Reflect.fields() returns the fields something has at runtime - if a field is declared as inline, it might not show up for instance. Similarly, if length is a propery with a getter, the accessors might show up instead (get_length), but I believe this depends on the target.

    Type.getClass() returns the runtime type of the object.


  • administrators

    Btw, in your original code snippet, you check puyo for null - couldn't puyoB be null still?

    if (puyo.overlaps(puyoB))
    {
    	return true;
    }
    

Log in to reply
 

Looks like your connection to HaxeFlixel was lost, please wait while we try to reconnect.