Box2D中的EXC_BAD_ACCESS与iOS中的CreateFixture

时间:2020-12-01 23:01:12

I have had multiple games on the AppStore for 5-6 years that use Cocos2D and Box2D. I've never had a problem with any of them crashing. Apple is making me update them or they'll be taken off of the AppStore. So I started to update them by updating Cocos2d and Box2d. After a few hours dealing with build errors I was a t a point where I could test. I tested in the simulator on 6 devices spanning different operating system versions. I also tested on my iPhone6 10.3. I even made screen grabs at different sizes. I uploaded an archive to TestFlight and then tested that on my device.... CRASH. I then went back to test on simulator and CRASH. Now it crashes every time at the same point. I have no idea why it worked for so long and now doesn't without any code changes.

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

I was getting the crash on CreateBody. I then moved all the code to after world->Step and now it crashes on CreateFixture. I enabled zombies and that doesn't give me any more insight.

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

The game begins and it creates 2 b2Body objects and 2 b2Fixture objects (a large ring). There is also another b2Body & b2Fixture that you can move up and down (a blimp). The object is to get the blimp to go through the rings. The rings move from right to left. Once you pass or fail that ring, the ring parts are destroyed and and new ring (2 b2Bodies & 2 b2Fixtures) is created. This SECOND RING is where the crash happens. (Again, for years this has worked perfectly starting with ios 4.3 -> 10) but now trying to update with XCode 8 it won't work (even though I tested for hours and it worked fine yesterday).

游戏开始,它创建了2个b2Body对象和2个b2Fixture对象(一个大环)。还有另一种b2Body&b2Fixture可以上下移动(飞艇)。目标是让飞艇通过环。戒指从右向左移动。一旦您通过或失败该环,环部件将被破坏,并且会创建新环(2 b2Bodies和2 b2Fixtures)。这个SECOND RING是发生崩溃的地方。 (再次,多年来这一切都完美地从ios 4.3开始 - > 10)但现在尝试用XCode 8更新它将无法工作(即使我测试了几个小时,它昨天工作正常)。

Here is the ring creation code: (written 4-5 years ago when I was learning Box2D)

这是戒指创作代码:( 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);
}

If I comment out the CreateFixture, It runs perfectly fine. I can't do this.

如果我注释掉CreateFixture,它运行得非常好。我不能这样做。

The crash is in b2Body.cpp:

崩溃发生在b2Body.cpp:

b2Fixture* b2Body::CreateFixture(const b2FixtureDef* def)
{

...

fixture->Create(allocator, this, def);

...

}

And in b2Fixture.cpp

并在b2Fixture.cpp

void b2Fixture::Create(b2BlockAllocator* allocator, b2Body* body, const b2FixtureDef* def)
{

...

m_shape = def->shape->Clone(allocator);

...

}

I have 5-6 apps that use Box2d & Cocos2d and I don't want to have to take them off the AppStore but I also can't start over on them. I have already written a version where the creation happens after world->Step but that didn't change anything, still crashes.

我有5-6个使用Box2d和Cocos2d的应用程序,我不想将它们从AppStore中删除,但我也无法重新开始。我已经编写了一个版本,其中创建发生在world-> Step之后但是没有改变任何东西,仍然崩溃。

This is the code that is deleting the bodies in the tick method:

这是在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);
    }

Hopefully someone can help me save these games from being removed from the AppStore. Any help is appreciated and keep in mind I haven't used Box2d in years so frankly I don't remember much about it.

希望有人可以帮助我保存这些游戏免于从AppStore中删除。任何帮助是值得赞赏的,请记住我多年没有使用Box2d,所以坦率地说我不记得太多了。

EDIT: I reverted back to the older version of Cocos2d and I'm back to crashing on CreateBody. More specifically:

编辑:我恢复到旧版本的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 {

     ...

    }
}

I always crash on index 6

我总是在索引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
}

Box2D中的EXC_BAD_ACCESS与iOS中的CreateFixture

So next in block is null so it crashes. Another forum said a person with very similar code was trying to destroy same object multiple times. I don't see that happening.

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

1 个解决方案

#1


0  

So the problem, as PaulMcKenzie pointed out, is the way that I am destroying bodies. This was originally written for Xcode 4.3 and now updating for Xcode 8.3 I have a crash problem. I have no knowledge of Box2D anymore so I went for the quick fix of Destroying the fixtures and hiding the sprites and then destroying the bodies after they go off the screen. This seems to work for me for now and since I can't spend time fixing it with (erase(remove_if()), the right way, it will do for now.

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

I am Answering this because this is the offending code located in the tick method:

我正在回答这个问题,因为这是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);
}

And it is important to rewrite this in the proper way to destroy a b2Body.

重要的是以正确的方式重写它以摧毁b2Body。

If someone writes the proper way to destroy the body I will mark it as the correct answer.

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

#1


0  

So the problem, as PaulMcKenzie pointed out, is the way that I am destroying bodies. This was originally written for Xcode 4.3 and now updating for Xcode 8.3 I have a crash problem. I have no knowledge of Box2D anymore so I went for the quick fix of Destroying the fixtures and hiding the sprites and then destroying the bodies after they go off the screen. This seems to work for me for now and since I can't spend time fixing it with (erase(remove_if()), the right way, it will do for now.

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

I am Answering this because this is the offending code located in the tick method:

我正在回答这个问题,因为这是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);
}

And it is important to rewrite this in the proper way to destroy a b2Body.

重要的是以正确的方式重写它以摧毁b2Body。

If someone writes the proper way to destroy the body I will mark it as the correct answer.

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