4

我将 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)

内部也会随机出错;遍历孩子,它会找到一个 NULL 并在 Cocos2d 内部代码上得出结论:

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

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

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

在这个项目中,cocos2d::CCCopying 对我来说已经是噩梦了;每次我看到它,我都知道有问题,但我不知道如何找到它。

我已经在 release() 删除行添加了一个断点;它没有被调用。就像我说的,我不会手动做任何类似的事情。

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

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

我希望有人能帮帮忙!

4

6 回答 6

3

有时 dynamic_cast 会返回 0,即使它的参数不是 0。例如,当您将超类强制转换为子类(所谓的“向下强制转换”)时,就会发生这种情况。查看本教程以获取更多信息:http ://www.cplusplus.com/doc/tutorial/typecasting/

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

于 2013-05-13T20:30:13.143 回答
1

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

您可以尝试打开保护 malloc

或者,您可以通过在可疑类(如 EnemySprite 的)解构器/构造器中放置一个静态 int 计数器来减少/增加,并在它低于零时中断/记录。

于 2013-05-06T08:31:33.647 回答
0

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

  1. 如果断点被命中,那可能是内存损坏。
  2. 如果断点未命中并且您得到 NULL,请深入研究getChildByTag(). 然后我要做的是替换this->getChildByTag()检查dynamic_cast<EnemySprite*>(this->getChildren()->objectAtIndex())是否有任何区别。
于 2013-05-15T13:02:28.667 回答
0

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

于 2013-05-10T05:50:03.833 回答
0

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

于 2014-09-24T12:05:11.210 回答
0

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

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

于 2013-05-14T14:54:27.040 回答