Box2D 在 b2BlockAllocator.cpp 中崩溃

Box2D crash in b2BlockAllocator.cpp

我最近刚开始将 Box2D 与 C++ 和 Visual Studio 2015 一起使用,我遇到了一个非常奇怪的错误,我在第 155 行遇到了由 b2BlockAllocator.cpp 引起的访问冲突。看起来一个array 被分配给某种 b2Block 链表结构,其下一个值为 null。这就是触发访问冲突的原因。

if (m_freeLists[index])
{
    b2Block* block = m_freeLists[index];
    m_freeLists[index] = block->next; // <- error occurs here.
    return block;
}
else
{...

但这就是奇怪的地方。我一直在开发一个供个人使用的游戏库,下面的代码用于在游戏库中的PhysicsObjectclass中实例化一个b2Body:

void PhysicsObject::onCreate()
{
    /**/
    b2BodyDef bodyDef;
    bodyDef.type = m_bodyType;
    bodyDef.position.Set((float)(m_x + m_width / 2) / (float)m_pLevel->getTileSize(), (float)(m_y + m_height / 2) / (float)m_pLevel->getTileSize());
    m_pBody = m_pLevel->getWorld().CreateBody(&bodyDef);

    b2PolygonShape shape;
    shape.SetAsBox((float)m_width / (float)m_pLevel->getTileSize() * 0.5f, (float)m_height / (float)m_pLevel->getTileSize() * 0.5f);

    b2FixtureDef fixtureDef;
    fixtureDef.shape = &shape;
    fixtureDef.density = 1.0f;
    fixtureDef.friction = 0.3f;
    m_pBody->CreateFixture(&fixtureDef); // <- This call is the last executed before the error.
    /**/
}

这是在游戏库中,它是一个 Visual Studio DLL 项目,并且运行良好。但是,当我将此 EXACT 代码移动到引用游戏库的测试项目中从 PhysicsObject 派生的 class 时,会发生崩溃。将每个对象分配给堆也没有什么区别,因为 Box2D 文档指出它们传递给的对象不保留引用。如果这有帮助,Box2D 是一个静态链接库。测试项目和游戏库具有完全相同的依赖关系并且处于相同的配置中。有谁知道为什么会发生这种情况?非常感谢任何帮助。

更新:

我发现了导致崩溃的原因,但不确定如何修复它。问题是 Box2D 的块分配器在世界创建 b2Body 之后不知何故变得腐败。这是分配前空闲块列表的样子:

Before allocation

创建 b2Body 后:

After allocation

如您所见,块列表中显然有损坏的内存。有谁知道为什么会这样?静态链接我的项目会解决这个问题吗?

我遇到的问题与从 DLL 中的代码传输到可执行文件中的代码之间发生的内存损坏有关。虽然我不确定这是为什么,但我认为它可能与 DLL Hell 有关。解决方案是让我的游戏库成为静态库而不是动态库。这只是将所有代码直接编译到可执行文件中,不会发生由转换引起的内存损坏。

我在创建 b2BodyDef 时错误地设置了 userData。 我认为 userData 导致了内存问题,并且当 b2Body 被销毁时出了点问题。 正确设置userData后问题解决。

我的游戏不会在 BlockAllocator 中崩溃,但会在 b2Contact::Destroy() 中崩溃。 发生在我身上的是:

  1. 我打电话给 b2World::Step()
  2. 让 b2ContactListener 派生 class 监听游戏逻辑的碰撞。 b2ContactListener::BeginContact() 被调用
  3. b2ContactListener::BeginContact() 在别处调用了函数 f()。
  4. f() 调用了 b2World re-update.
  5. b2World 删除了一些 b2Contacts,它们在 2)
  6. 时仍在堆栈中
  7. 逻辑完成后,我被带回 2) 处的 BeginContact()。 BeginContact() 然后访问删除的对象,导致崩溃。

希望对解决崩溃问题有所帮助。我的 Visual Studio 调试器也显示无法读取内存,这让我很困惑。我认为这是 Box2D 的错误但是......哈。错误是 b