Box2D中的EXC_BAD_ACCESS与iOS中的CreateFixture

时间:2017-05-02 17:42:06

标签: c++ ios cocos2d-iphone xcode8 box2d

我在AppStore上玩了多个游戏,使用Cocos2D和Box2D已经有5到6年了。我从来没有遇到过任何问题。 Apple正在让我更新它们,否则它们将从AppStore中删除。所以我开始通过更新Cocos2d和Box2d来更新它们。在处理构建错误几个小时后,我才能测试。我在模拟器中测试了6种不同操作系统版本的设备。我还在我的iPhone6 10.3上测试过。我甚至制作了不同尺寸的屏幕抓取。我上传了一个存档到TestFlight,然后在我的设备上测试了.... CRASH。然后我回去测试模拟器和CRASH。现在它每次都在同一时间崩溃。我不知道为什么它工作了这么久,现在没有任何代码更改。

我在CreateBody上遇到了崩溃。然后我将所有代码移到了world-> Step之后,现在它在CreateFixture上崩溃了。我启用了僵尸,并没有给我更多的洞察力。

游戏开始,它会创建2个b2Body对象和2个b2Fixture对象(一个大环)。还有另一个b2Body& b2你可以上下移动的混合物(飞艇)。目标是让飞艇通过环。戒指从右向左移动。一旦您通过或失败该环,环部件将被破坏,并且会创建新环(2 b2Bodies& 2 b2Fixtures)。这个SECOND RING是发生崩溃的地方。 (再次,多年来这一切都完美地从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
}

enter image description here

所以块中的下一个是null,所以它崩溃了。另一个论坛说一个代码非常相似的人试图多次销毁同一个对象。我没有看到这种情况发生。

1 个答案:

答案 0 :(得分:0)

正如PaulMcKenzie指出的那样,这个问题就是我摧毁尸体的方式。这最初是为Xcode 4.3编写的,现在更新为Xcode 8.3我遇到了崩溃问题。我不再知道Box2D所以我去快速修复了破坏固定装置并隐藏精灵然后在它们离开屏幕后摧毁了尸体。这似乎对我现在有用,因为我不能花时间修复它(擦除(remove_if()),正确的方法,它现在会做。

我正在回答这个问题,因为这是位于 tick 方法中的有问题的代码:

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);
}

重要的是以正确的方式重写这个以破坏b2Body。

如果有人写出正确的方法来摧毁身体,我会将其标记为正确答案。