Issue with this->addChild calls

Hi.

I am quite new on cocos2dx development and I have been trying to chase an issue I have in my code for two days with no satisfactory results.

The issue is that when I call: this->addChild() on a CCLayer subclass I have end up with “this” pointer setted to NULL value when the call to addChild finish, and I don´t know why. The code is the following:

I have my own CCLayer subclass in which I try to add a child on his init method:

#include "cocos2d.h"

USING_NS_CC;

namespace MyLayerNS{

class MyLayer: public CCLayer{

private:
   CCPoint _position;
   CCSize _size;
   CCLabelTTF* pLabel;

public:
   ~MyLayer();
   void setPosition(CCPoint position);
   void setSize(CCSize size);

   virtual bool init();

   // implement the static instance
   CREATE_FUNC(MyLayer);
};
}

And this are my definitions

#include "MyLayer.h"
USING_NS_CC;

namespace MyLayer{

MyLayer::~MyLayer()
{ }

void MyLayer::setSize(CCSize size)
{
   _size.width = size.width;
   _size.height = size.height;
}
void MyLayer::setPosition(CCPoint position)
{
   _position = ccp(position.x, position.y);
}

bool MyLayer::init(){
   bool bRet = false;
   do
   {
       CC_BREAK_IF(!CCLayer::init());
       pLabel = CCLabelTTF::create("Some ttf label", "Arial", 24);
       CC_BREAK_IF(! pLabel);
       pLabel->retain();

       CCPoint lp = CCPoint(10, 10);
       pLabel->setPosition(lp);

       this->addChild(pLabel, 1);
       bRet=true;
   }while (0);
   return true;
}

The issue is on the call to this->addChild(pLabel, 1); It executes it but jumps straight out of the do while statement with this=NULL

On the HelloWorldScene I have added that new layer on the _scene()_ method:

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

       // 'layer' is an autorelease object
       HelloWorld *layer = HelloWorld::create();
       CC_BREAK_IF(! layer);

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

       MyLayerNS::MyLayer* someLayer= MyLayerNS::MyLayer::create();
       CC_BREAK_IF(!someLayer);
       someLayer->retain();
       someLayer->setPosition(VisibleRect::leftTop());
       someLayer->setSize(CCSize(10,10));
       scene->addChild(someLayer,1);      
   } while (0);

   // return the scene
   return scene;
}

On that code the MyLayerNS::MyLayer::create() ends up calling MyLayerNS::MyLayer::init() where I have the issue.

Any idea how I can solve this problem?

Thanks.

  1. I don’t see the need for that do{...}while() block.
  2. You are using retain() without a matching release().
  3. Avoid using the CREATE_FUNC() and CC_BREAK_IF() macros. Well, avoid using macros in general. Implement your own create() method if necessary.
  4. It is likely that the MyLayer instance failed to be allocated inside the create() method (during the new instruction), which I can’t tell exactly because you are using a macro.
  5. You are overloading setPosition() incorrectly and may cause unnecessary glitches. You do not have to re-implement them if you’re not going to change its behavior.

Hi Lance

Thanks for the quick response.

The do{...}while Is just there to be able to jump out of it with the cocos2dx macro CC_BREAK_IF() Sure there are some other ways to achieve that.

Thanks for pointing the unmatching reatin()/@release()@ I forgot that in the destructor.

You are rigth that setPosition() may be wrong but I dind´t intend to overload that function just use a common name that I didn´t know was on the super class.

About the create() I was suspicious about that. The macro expands to this:

/**
 * define a create function for a specific type, such as CCLayer
 * @__TYPE__ class type to add create(), such as CCLayer
   /
  #define CREATE_FUNC(TYPE) \
  static TYPE create() \
{ \
    TYPE *pRet = new TYPE(); \
    if (pRet && pRet->init()) \
  { \
        pRet->autorelease(); \
        return pRet; \
    } \
    else \
  { \
        delete pRet; \
        pRet = NULL; \
        return NULL; \
    } \
  }

And I detect that the pRet->init() is being called calling to MyLayer::init() so If new failed it should throw but it isn´t throwing and is giving a valid memory address and that is being wiped when calling addChild() inside the MyLayer::init()

I don´t know if the wrong overloading of setPosition() could end up in this kind of issue.