Неправильно уничтожение класса btKinematicCharacterController
При использовании библиотеки Bullet Physics я создаю класс btKinematicCharacterController. И у меня всё идёт хорошо до тех пор, пока я не выхожу из приложение. Во время очистки динамически выделенной памяти у меня появляется ошибка: "fish: Job 1, './some_app' terminated by signal SIGSEGV (Address boundary error)". Но стоит мне удалить создание Character из исходно кода, как ошибка исчезает. Вот код удаления Character:
world->removeAction(controller);
btCollisionShape* shape = controller->getGhostObject()->getCollisionShape();
btPairCachingGhostObject* ghost_body = controller->getGhostObject();
delete controller;
delete ghost_body;
delete shape;
Вот код удаления мира:
void GTEngine::Physics::service_info::WorldData::del()
{
for (size_t i = 0; i < Constrains.size(); i++)
Constrains[i]->del(world);
Constrains = {};
for (size_t i = 0; i < RigidBodies.size(); i++)
RigidBodies[i]->del(world);
RigidBodies = {};
for (size_t i = 0; i < Characters.size(); i++)
Characters[i]->del(world);
Characters = {};
delete dispatcher;
delete collisionConfig;
delete solver;
delete broadphase;
delete world;
}
Я уверен что объекты создаются верно, так как при создани ошибок нет. А они сами работают (к ним можно приминить силу, реагируют друг на друга)
UPD1: Я создаю character с помощью данного кода:
worldData->broadphase->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback());
btPairCachingGhostObject* ghost_body = new btPairCachingGhostObject();
btTransform t;
t.setIdentity();
t.setOrigin(pos);
ghost_body->setWorldTransform(t);
btCapsuleShape* shape = new btCapsuleShapeX(shape_size.x, shape_size.y);
ghost_body->setCollisionShape(shape);
ghost_body->setCollisionFlags(btCollisionObject::CF_CHARACTER_OBJECT);
controller = new btKinematicCharacterController(ghost_body, shape, 0.1);
controller->setGravity(worldData->world->getGravity());
worldData->world->addCollisionObject(ghost_body, btBroadphaseProxy::CharacterFilter,
btBroadphaseProxy::StaticFilter | btBroadphaseProxy::DebrisFilter);
worldData->world->addAction(controller);
UPD2: Ошибка возникает при удалении мира:
delete world;
Я думаю что в мире сохраняются какие то ссылки, но я не уверен в этом.
Ответы (2 шт):
Ответ затаился в вопросе:
Когда вызываете delete controller
- вы, собственно, освобождаете память, занимаемую controller
и все связанные с ним объекты становятся недоступными, поэтому, когда вызывается controller->getGhostObject()
- происходит неопределенное поведение, т.к. controller
уже был удален. Попробуйте просто поменять порядок удаления, ну и как рекомендация - лучше добавлять проверку на nullptr перед удалением.
void deleteCharacter(btKinematicCharacterController* controller) {
if (controller) {
btPairCachingGhostObject* ghost_body = controller->getGhostObject();
if (ghost_body) {
btCollisionShape* shape = ghost_body->getCollisionShape();
world->removeAction(controller);
delete shape;
delete ghost_body;
}
delete controller;
}
}
А еще можно посмотреть в сторону умных указателей - unique_ptr
и shared_ptr
.
Если ошибка осталась, то либо добавь деталей к вопросу(а то, смотря на код, довольно тяжело представить, что у тебя там написано), пройдись отладчиком
Проблема была в том, что я не удалял объект коллизии и он оставался в мире. Вот мой не правильный код:
world->removeAction(controller);
btCollisionShape* shape = controller->getGhostObject()->getCollisionShape();
btPairCachingGhostObject* ghost_body = controller->getGhostObject();
delete controller;
delete ghost_body;
delete shape;
И вот как это нужно делать (правильный код и спасибо cith за совет):
{
if (isDelete) return; else isDelete = true;
if (!controller) return;
btPairCachingGhostObject* ghost_body = controller->getGhostObject();
if (ghost_body)
{
btCollisionShape* shape = ghost_body->getCollisionShape();
world->removeCollisionObject(ghost_body);
world->removeAction(controller);
delete shape;
delete ghost_body;
}
delete controller;
controller = nullptr;
}