子对象(看似)随机设置为NULL或“非法对象”;怎么调试呢?

时间:2013-05-04 14:12:08

标签: c++ xcode cocos2d-x

我使用Cocos2d-x进行我从Cocos2d-iphone移植的游戏。最初的程序员似乎已经使用了Objective-C的“特性”来防止对nil对象的调用崩溃,这是一种做很多草率事情的方法。

如果这与我不知道的相关,但是,在我的代码中,我从不手动调用release(),当然也不会删除或类似的东西。我甚至根本没有调用 - > removeObject()(尽管这不会导致与我相同的问题)。

现在的问题是:当游戏运行时,随机时刻(它们不会是随机的,但现在看起来很明显)子节点被设置为NULL。这不仅会影响我的代码,还会影响Cocos2d内部。示例:

    CCLog("----------------");
    for(int j = 0; j < this->getChildren()->count(); j++)
    {
        CCObject *child = this->getChildren()->objectAtIndex(j);
        EnemySprite *enemy = dynamic_cast<EnemySprite*>(child);
        if (enemy != NULL) {
            CCLog("Enemy with tag %d found", enemy->getTag());
        }
    }
    EnemySprite *enemy = dynamic_cast<EnemySprite*>(this->getChildByTag(i));
    if (enemy == NULL) {

        CCLog("Now enemy with %d is NULL :(", i);
    }

在getChildren()外观中,所有带有标签的敌人都在那里并打印出来;

  • 发现标签1000的敌人
  • 找到标签1001的敌人
  • 找到标签1002的敌人

在比赛期间,它会显示很多,直到它显示出来;

  • 发现标签1000的敌人
  • 找到标签1001的敌人
  • 找到标签1002的敌人
  • 现在1001的敌人是NULL:(

并崩溃。

在我看来,上面的代码应该是不可能的,因为我刚刚检查,验证并打印了那个对象......

但更有趣(也许只有我,也许这是一些愚蠢的错误),这个

 this->getChildByTag(i)

内部也随机出错;遍历这些孩子,它会在Cocos2d内部代码中找到一个NULL和conk out:

        if(pNode && pNode->m_nTag == aTag)
            return pNode;

然后pNode不是NULL(这就是断言不触发的原因)但看起来像这样:

http://o7.no/137JXC4(截图)

在这个项目中,cocos2d :: CCCopying对我来说已经是噩梦了。我每次看到它都知道有些事情是错的,我不知道如何找到它是什么。

我已经在release()删除行添加了一个断点;它没有被召唤。就像我说的那样,我手动不做那样的事。

我使用Xcode / iOS进行调试,但Android上的行为是相同的(但在我的计算机上,Eclipse比Xcode慢,特别是在调试期间)。

我知道很难给我一个解决方案/原因;如果有人能告诉我如何解决这个问题,我会很高兴。它在整个(非常大的)代码库中随机发生,我不知道如何找到这个问题...

我希望有人可以提供帮助!

6 个答案:

答案 0 :(得分:3)

有时dynamic_cast返回0甚至很难,它的参数不是0.例如,当您将超类转换为子类(所谓的“向下转换”)时会发生这种情况。有关详细信息,请查看本教程:http://www.cplusplus.com/doc/tutorial/typecasting/

我可以想象,如果列表中的元素具有通用(无关)超类型,则可能是您的问题。

答案 1 :(得分:1)

正如你所说,这很难说,但这里有两个想法。

您可以尝试启用guard malloc

或者,你可能会从你的可疑类(如EnemySprite的)解构器/构造函数中放入一个静态int计数器来减少/递增,并在它低于零时打破/记录。

答案 2 :(得分:0)

我只看到j什么是i的定义? 我相信它在CCLog("Now enemy with %d is NULL :(", i);之后崩溃了 因为这条线已被记录,所以它绝对不会崩溃。

答案 3 :(得分:0)

默认情况下,CCObjects受AutoReleasePool约束,这意味着Cocos2D-x将管理何时释放该对象。如果对这些对象使用静态构造函数,则可以调用object-&gt; retain()和object-&gt; release(),以便自己管理内存。

来源:http://www.cocos2d-x.org/projects/cocos2d-x/wiki/Reference_Count_and_AutoReleasePool_in_Cocos2d-x

答案 4 :(得分:0)

如果某些东西将敌人对象更改为NULL,我会做的是在敌人的地址设置一个数据断点(对于1001)。比,

  1. 如果遇到断点,则可能是内存损坏。
  2. 如果未点击断点并且您获得NULL,请深入研究getChildByTag()。我会做的是用this->getChildByTag()替换dynamic_cast<EnemySprite*>(this->getChildren()->objectAtIndex()),检查是否有任何区别。

答案 5 :(得分:0)

Build Settings->Other C Flags->Debug and add -o0标记并尝试调试。