Alberto SM [SOLVED] "Unhandled exception" when trying to access a CCActionInterval from another function... (C++)
Posts 17
Added by Alberto SM over 1 year ago

[SOLUTION AS OF 14/02/12]
If you plan on storing a CCAction in any of its forms (CCActionInterval, CCFiniteTimeAction, etc) into a variable (pointer, most probably): Always retain the variable or its data will be scrambled!
Example:

    CCFiniteTimeAction* act = CCMoveTo::actionWithDuration( 1, ccp(250,250) );
    _sprite->runAction(act);
    act->retain(); // DO THIS OR SAY HELLO TO AN UNHANDLED EXCEPTION! :D

Thanks to Walzer Wang and Minggo Zhang for their help! =============================================================================================================================================================================
[ORIGINAL POST]
Hi guys, I'm trying to keep track of the status of the animations on some sprites. I've narrowed down my code so it's easy to see where the problem is born from.

The main problem is: I want to move a sprite, and turn its color into purple when it finishes the CCMove action. What I do is define the CCActionInterval (also tried with CCFiniteTimeAction) as a member of the class, define its type on the onEnter function, and try to know it's status on the update function. Here's the code:

ON THE HEADER

class QuizLayer : public CCLayer{
private:
    CCSprite* sprite; // The sprite
    CCActionInterval* act;
public:
    void onEnter();
    void update(ccTime dt);

    static QuizLayer* node(){
        QuizLayer* pNode = new QuizLayer();
        pNode->autorelease();
        return pNode;
    }
};

ON THE CPP

void QuizLayer::onEnter(){
    CCLayer::onEnter();
    sprite = CCSprite::spriteWithFile("hello.png");
    ccs->setPosition( ccp(100,100) );
    addChild(sprite);

    act = CCMoveTo::actionWithDuration( 2, ccp(200,200) ); // Definition of the actionInterval
    act->setTag(111);
    sprite->runAction(act);
    this->schedule( schedule_selector(QuizLayer::update) ); // Add the update function to the scheduler
}

void QuizLayer::update(ccTime dt){
    // OPTION 1 - Call "act" directly
    if (act->isDone()){
        sprite->setColor(cPurple); // ccColor3B cPurple = {190,0,214}; // Turn sprite color into purple
    }
    // OPTION 2 - Get the action by its TAG in the sprite
    if (sprite->getActionByTag(111)->isDone()){
        ccs->setColor(cPurple);
    }

}

When arriving at any of the IFs on the update function, VS2010 prompts me the following:

(!) Unhandled exception at 0x010d55e9 in TSP.win32.exe: 0xC0000005: Access violation reading location 0x00000000.

I don't know if this is even achievable, but if someone can lend me a hand, I'll appreciate it very much!!!
Thanks in advance!

Zhe Wang RE: "Unhandled exception" when trying to access a CCActionInterval from another function... (C++)
Posts 1665
Location Amoy, China
Added by Zhe Wang over 1 year ago

The problem is probably caused by the autorelease pool. The mechanic is described here http://www.cocos2d-x.org/boards/6/topics/678?r=696
In your node() function

 static QuizLayer* node(){
        QuizLayer* pNode = new QuizLayer();   // QuizLayer::m_uRefCount = 1
        pNode->autorelease();    // will be release at the end of this msg loop
        return pNode;
    }

If you haven't call MyScene->addChild( QuizLayer::node() ), or QuizLayer::node()->retain() in you scene, QuizLayer object will be released before update() call in next message loop.
It's only my conjecture. :)

Keep it simple and stupid.

Alberto SM RE: "Unhandled exception" when trying to access a CCActionInterval from another function... (C++)
Posts 17
Added by Alberto SM over 1 year ago

Thanks for the reply Walzer! :D Though I'm afraid I'm still stuck on this...:(
I can't say that I understand completely the behaviours of autorelease(), retain(), and so on, I'm kinda new to all of this methods :( but from what I've seen I think my problem resides on the main scene.
I dumbed down my code so that it's (maybe) easier to read... The main scene is taken from the layer Test now.
AppDelegate

...
CCScene *pScene = GameStarter::scene();
CCDirector::sharedDirector()->runWithScene(pScene);
...

GameStarter:public CCLayer

class GameStarter : public CCLayer{
public:
    static cocos2d::CCScene* scene(){ // AppDelegate calls this
        return Test::scene();
    }
};

Test:public CCLayer -- HEADER

class Test : public CCLayer{
private:
    CCSprite* ccs; // Test sprite
    CCFiniteTimeAction* act;
public:

    static Test* node();
    static CCScene* scene(); // What is requested by GameStarter and AppDelegate

    void onEnter();
    void update(ccTime dt);
};

Test:public CCLayer -- CPP

Test* Test::node(){
    Test* pNode = new Test();
    pNode->autorelease();
    return pNode;
}

CCScene* Test::scene(){
    CCScene * scene = NULL;
    do {
        // 'scene' is an autorelease object
        scene = CCScene::node();
        CC_BREAK_IF(! scene);

        // 'layer' is an autorelease object
        Test *layer = Test::node();
        CC_BREAK_IF(! layer);

        // add layer as a child to scene
        scene->addChild(layer);

    } while (0);

    // return the scene
    return scene;
}

void Test::onEnter(){
    CCLayer::onEnter();

    ccs = CCSprite::spriteWithFile("HELLO.PNG");
    ccs->setPosition( ccp(100, 100) );
    addChild(ccs);

    act = CCMoveTo::actionWithDuration( 1, ccp(250,250) );
    ccs->runAction(act);
    this->schedule( schedule_selector(Test::update) ); // Add the update function to scheduler
}

void Test::update(ccTime dt){
    if (act->isDone()){
        sprite->setColor(cPurple); // ccColor3B cPurple = {190,0,214}; // Turn sprite color into purple
    }
}

----
So simple, and it still breaks down on the same thing! I don't know what to do...
I'm going to conitue try to find this issue and learn more about autorelease() and his "friends", but if anyone notices something out of place, please drop a line!
Thanks in advance.

Minggo Zhang RE: "Unhandled exception" when trying to access a CCActionInterval from another function... (C++)
Posts 1654
Added by Minggo Zhang over 1 year ago

I think there are two errors:
1. onEnter() may be called many times, so don't init "ccs" and "act" in it. I think call init() in constructor is a suitable method.
2. You should retain "css" and "act" after you invoke CCSprite::spriteWithFile() and CCMoveTo::actionWithDuration(), or it will be released, because CCSprite::spriteWithFile() and CCMoveTo::actionWithDuration() all call autorelease().

Alberto SM RE: "Unhandled exception" when trying to access a CCActionInterval from another function... (C++)
Posts 17
Added by Alberto SM over 1 year ago

OMG that's what it was:

When I retained the action, it automatically worked!! (/)

Thank you SO MUCH Minggo, I'll update my first post for other people to see :D


(1-4/4)