【发布时间】:2017-05-02 17:42:06
【问题描述】:
5-6 年来,我在 AppStore 上有多个使用 Cocos2D 和 Box2D 的游戏。我从来没有遇到过任何崩溃的问题。 Apple 让我更新它们,否则它们将被从 AppStore 中删除。所以我开始通过更新 Cocos2d 和 Box2d 来更新它们。在处理构建错误几个小时后,我可以测试了。我在模拟器中测试了跨越不同操作系统版本的 6 台设备。我还在我的 iPhone6 10.3 上进行了测试。我什至制作了不同尺寸的屏幕抓取。我将存档上传到 TestFlight,然后在我的设备上进行了测试.... CRASH。然后我回去在模拟器和 CRASH 上进行测试。现在它每次都在同一点崩溃。我不知道为什么它工作了这么久,现在没有任何代码更改。
我在 CreateBody 上遇到了崩溃。然后我将所有代码移到 world->Step 之后,现在它在 CreateFixture 上崩溃。我启用了僵尸,但这并没有给我更多的洞察力。
游戏开始,它创建了 2 个 b2Body 对象和 2 个 b2Fixture 对象(一个大环)。还有另一个可以上下移动的 b2Body 和 b2Fixture(飞艇)。目的是让飞艇穿过环。环从右向左移动。一旦您通过或未通过该环,环部件将被破坏并创建新环(2 b2Bodies 和 2 b2Fixtures)。第二个环是崩溃发生的地方。 (同样,多年来,从 ios 4.3 -> 10 开始,它一直运行良好),但现在尝试用 XCode 8 更新它不起作用(即使我测试了几个小时,昨天它运行良好)。
这里是环创建代码:(4-5年前我学习Box2D时写的)
-(void)addRing{
int r = (arc4random() % 250) + 160;
CGPoint p = ccp(SCREEN_WIDTH+100,r);
ring_bottom = [CCSprite spriteWithFile:@"ring_bottom.png"];
[self addChild:ring_bottom z:BLIMP_BOTTOM tag:bTagRingBottom];
ring_bottom.position = ccp(p.x, p.y);
// Define the dynamic body.
//Set up a 1m squared box in the physics world
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
bodyDef.position.Set(p.x/PTM_RATIO,p.y/PTM_RATIO);
bodyDef.userData = ring_bottom;
bodyDef.fixedRotation=YES;
bodyDef.gravityScale=0;
//bodyDef.position.Set(0.0, 0.1);
_ringBottom = _world->CreateBody(&bodyDef);
b2PolygonShape dynamicBox;
dynamicBox.SetAsBox(0.25, 10.0, b2Vec2(0.0,13.00), 0.0);
// Define the dynamic body fixture.
b2FixtureDef fixtureDef;
fixtureDef.shape = &dynamicBox;
fixtureDef.density = 10.0f;
fixtureDef.friction = 0.0f;
fixtureDef.isSensor = true;
_ringBottom->CreateFixture(&fixtureDef);
//----------------------------------------------------
ring_top = [CCSprite spriteWithFile:@"ring_top.png"];
[self addChild:ring_top z:GAME_LAYER tag:bTagRingTop];
ring_top.position = ccp(p.x, p.y);
// Define the dynamic body.
//Set up a 1m squared box in the physics world
b2BodyDef bodyDef2;
bodyDef2.type = b2_dynamicBody;
bodyDef2.position.Set(p.x/PTM_RATIO,p.y/PTM_RATIO);
bodyDef2.userData = ring_top;
bodyDef2.fixedRotation=YES;
bodyDef2.gravityScale=0;
_ringTop = _world->CreateBody(&bodyDef2);
b2PolygonShape dynamicBox2;
dynamicBox2.SetAsBox(0.25, 10.0, b2Vec2(0.0,-13.00), 0.0);
// Define the dynamic body fixture.
b2FixtureDef fixtureDef2;
fixtureDef2.shape = &dynamicBox2;
fixtureDef2.density = 10.0f;
fixtureDef2.friction = 0.0f;
fixtureDef2.isSensor = true;
_ringTop->CreateFixture(&fixtureDef2);
}
如果我注释掉 CreateFixture,它运行得非常好。我做不到。
崩溃在 b2Body.cpp 中:
b2Fixture* b2Body::CreateFixture(const b2FixtureDef* def)
{
...
fixture->Create(allocator, this, def);
...
}
在 b2Fixture.cpp 中
void b2Fixture::Create(b2BlockAllocator* allocator, b2Body* body, const b2FixtureDef* def)
{
...
m_shape = def->shape->Clone(allocator);
...
}
我有 5-6 个使用 Box2d 和 Cocos2d 的应用程序,我不想将它们从 AppStore 中删除,但我也无法重新开始使用它们。我已经写了一个版本,创建发生在 world->Step 之后,但这并没有改变任何东西,仍然崩溃。
这是在 tick 方法中删除正文的代码:
std::vector<b2Body *>toDestroy;
...
std::vector<b2Body *>::iterator pos2;
for(pos2 = toDestroy.begin(); pos2 != toDestroy.end(); ++pos2) {
b2Body *body = *pos2;
if (body->GetUserData() != NULL) {
CCSprite *sprite = (CCSprite *) body->GetUserData();
[self removeChild:sprite cleanup:YES];
}
_world->DestroyBody(body);
}
希望有人可以帮助我避免这些游戏被从 AppStore 中删除。感谢您提供任何帮助,请记住,我已经很多年没有使用过 Box2d,所以坦率地说,我不太记得它了。
编辑: 我恢复到了旧版本的 Cocos2d,我又回到了 CreateBody 上的崩溃。更具体地说:
b2BlockAllocator.cpp
void* b2BlockAllocator::Allocate(int32 size){
...
if (m_freeLists[index]){
b2Block* block = m_freeLists[index];
m_freeLists[index] = block->next; <--------------CRASH
return block;
} else {
...
}
}
我总是在索引 6 上崩溃
> Printing description of this->m_freeLists:
(b2Block *[14]) m_freeLists = {
[0] = 0x0000000000000000
[1] = 0x0000000103ca4060
[2] = 0x0000000103ca0080
[3] = 0x0000000100b30120
[4] = 0x0000000000000000
[5] = 0x0000000103ca80a0
[6] = 0x0000000300b2c180
[7] = 0x0000000104240000
[8] = 0x0000000000000000
[9] = 0x000000010423c140
[10] = 0x0000000000000000
[11] = 0x0000000000000000
[12] = 0x0000000000000000
[13] = 0x0000000000000000
}
所以块中的下一个是空的,所以它崩溃了。另一个论坛说,一个代码非常相似的人试图多次破坏同一个对象。我没有看到这种情况发生。
【问题讨论】:
-
在最后一组代码中,您是否删除了迭代器当前指向的项目?如果是这样,那么您的迭代器将被无效,因此在不调用未定义行为的情况下无法递增它。
-
如果是这样的话,这似乎永远不会奏效。我刚刚注意到的一件事是,如果您成功通过了游戏中的第一个环,它会在销毁旧环之前调用 addRing 并在 Destroy 之前崩溃。我不确定 Destroy 是否是问题所在。
-
如果是这样的话,这似乎永远不会奏效——“未定义的行为”意味着——行为未定义。这包括看起来工作正常。直到现在您才看到问题(如果问题正在增加无效的迭代器)。
-
你是说它在尝试销毁时崩溃?如果 Destroy 是问题,那么 CreateFixture 代码中会发生异常吗?如果是这样,这如何适应在调用 Destroy 之前崩溃?
-
我只是在查看您发布的代码。由于您没有提供minimal reproducible example,我不知道何时、何地或如何调用您的例程。我的意思是,如果您以这种方式编写了一个循环,您使用迭代器递增到下一个项目,如果迭代器(在本例中为
pos2)指向您刚刚的项目删除,执行++pos2是未定义的行为,因为迭代器已失效。从向量中删除项目的安全方法(我不知道方括号中的内容是什么意思)是使用erase / remove_if,从而消除编写循环。
标签: c++ ios cocos2d-iphone xcode8 box2d