Сбой при удалении указателя

Редактировать:

Я реализовал конструкторы копирования (оба из предложенного ответа). Я сделал это в своем классе контроллера, а также эквивалентные версии в его подклассах. Тем не менее, это не решило проблему. Кроме того, счетчик и консольный комментарий в removePawn() Функция (единственное место в программе, которая называется delete) показывает, что она вызывается только один раз.

Более подробно, есть один экземпляр каждого подкласса (не указатели). Они объявлены в моем world учебный класс. Оба используются в качестве параметров в одном и том же world методы классов через baseController указатели класса. Проблема в том, что оба проходят одинаковые процессы в одном и том же порядке, если один класс имеет removePawn() называется, программа в порядке и будет работать постоянно. Однако, если второй класс имеет removePawn() (удалить специально) вызывается на нем, он сбивает программу по этой инструкции.

Я также проверил адреса. Адрес указателя сразу после выделения идентичен адресу в точке удаления.

Дополнительная информация: Я получу ошибку сегментации при закрытии программы ТОЛЬКО в случае, если игрок убит (удален, затем дана новая пешка). Однако, если программа запускается, затем закрывается без какого-либо дополнительного первого и последнего удаления, тогда она работает отлично.

Оригинал:

У меня немного проблемы с указателями. Я понимаю их и считаю, что мой код достаточно надежен, однако при вызове этого раздела кода, похоже, происходит полный сбой.

Pawn — это basePawn *, инициализированный значением NULL.

if (pawn != NULL)
{
cout << "Calling delete.\n";
delete pawn;
pawn = NULL;
}

Это университетское задание для программы PS2, поэтому моя отладка ограничена простой печатью на консоль.

Удаление строки удаления позволяет запускать основной раздел new / delete несколько раз, однако в конечном итоге он тоже вылетает (я полагаю, это связано с тем, что предел памяти достигнут, однако я не уверен)

Я проверил все обычные преступники, указатель инициализируется нулем и удаляется только один раз (всегда вызывается также новый).

Возможно, я совершаю довольно очевидную ошибку, но понятия не имею. Любые предложения будут великолепны. (Я могу разместить больше кода, если это необходимо).

Редактировать:

Вот как работает структура кода.

basePawn — это класс с некоторыми довольно простыми методами, представляющими персонажа.

Контроллер — это класс с указателем на basePawn (изначально установленный в NULL), который используется в качестве мозга персонажа (под управлением AI или игрока). Он содержит метод removePawn.

void controller::removePawn()
{
if (pawn != NULL)
{
cout << "Calling delete.\n";
delete pawn;
pawn = NULL;
}
}

Этот метод вызывается в деструкторе. Он также вызывается, когда пешка убирается с уровня.

У этого также есть метод возрождения.

if (pawn == NULL)
{
respawnCounter++;

if (respawnCounter >= respawnTime)
{
//Switch block to change class
pawn = new basePawn;

if (pawn !=NULL)
{
pawn->boardY = 4; //Will be random
pawn->boardX = 5; //Will be random

respawnCounter = 0;

pawn->setIdle();

return true;
}
}
}

Редактировать:

файл заголовка baseController

#ifndef _BASEPAWNCONTROLLER_H
#define _BASEPAWNCONTROLLER_H

#include "basePawn.h"#include "textureManager.h"#include "direction.h"#include "vector2f.h"
//Used to control pawns
//Allows the same commands to be used to control different pawns
class basePawnController
{
private:
protected:
basePawn *pawn;

int respawnCounter,
respawnTime;

vector2f    targetDest;

bool        bMoving,
bTarget;

void        removePawn();

public:

bool    bFirstFrameDead;

basePawnController();
virtual ~basePawnController();

virtual void update();

basePawn *getPawn();
void setPawn(basePawn *p);
void setTarget(float x, float y);
direction getDir();
bool isMoving();
bool hasTarget();

virtual bool respawn();
virtual void render(textureManager &tManager);

virtual bool wantsPawn();
virtual void giveTargetInfo(direction d, int n);
};

#endif

0

Решение

Учитывая, что это PS2, я предполагаю, что у вас нет доступа к C ++ 11, а с ним — умные указатели (std::unique_ptr и т. д.) и т. д. Если Boost или C ++ 11 не подходят, вы должны уделить время и изучить, как реализовать базовые функциональные возможности интеллектуального указателя — это значительно ослабит психическое напряжение. Но давайте предположим, что это не вариант.

Обратите внимание, что это наиболее вероятный сценарий, который происходит из-за скудного описания проблемы, собранного из вопроса и комментариев.

Вы пытаетесь использовать RAII путем освобождения ресурсов, таких как пешка, когда экземпляр контроллера выходит из области видимости, так как вы вызываете removePawn в деструкторе — это хорошо. Тем не менее, существует множество способов, которыми экземпляр класса может потерять данные / выброс, если вы не предоставите нетривиальные реализации оператора копирования и реализации конструктора копирования в сочетании с указателями и распределением кучи.

Вы должны действительно реализовать дополнительную функциональность, которая управляет копированием, что может происходить так, как вы этого не ожидаете. Если вы сами не управляете этим, код, возможно, запускается несколько раз и позволяет как-то копировать контроллер, передавая его функции или тому подобному — он создаст новый контроллер со старыми данными. Но это мелкая копия, адрес basePawn, который, как мы предполагаем, действителен, будет скопирован, но он не установит для экземпляра умирающего значение 0 / NULL,

После того, как старый выходит из области видимости, вызывается его деструктор. И поскольку вы не сделали недействительным старый указатель, он удалит ту же пешку, на которую теперь ссылаются два разных объекта. И когда вы заявляете delete pawn; Через некоторое время — бум.

Вам нужны эти два правильно реализованные:

basePawnController(basePawnController& that);
basePawnController& operator=(basePawnController& that);

Не попадитесь в ловушку, объявив это const, это не вариант, когда вы играете с необработанными указателями. То, что должно произойти, в соответствии с этим, вы можете реализовать одно с точки зрения другого:

// Copy constructor
basePawnController::basePawnController(basePawnController& rhs) {

*this = rhs; // invokes basePawnController::operator=()

}

// Copy assignment operator
basePawnController& basePawnController::operator=(basePawnController& rhs) {

// copy your stuff and now the basePawn
pawn = rhs.pawn; // Copy the address...
rhs.pawn = 0; // ...but make sure the old instance doesn't troll you.

return *this;

}

Мой лучший совет для вас — исследовать прозрачность собственности с помощью умных указателей, используя средства RAII. Программирование должно быть приятным.

1

Другие решения

Ну, вы, ребята, были почти правы.

После добавления конструктора копирования и оператора присваивания я выполнил больше проверок, чтобы увидеть, где на самом деле возникали мои проблемы. Оказывается, это не имело ничего общего с моими классами контроллеров напрямую, а с моими классами пешки и мира.

У моей пешки есть вектор поврежденияNode *, который я не удалял. Не большая проблема, так как у меня был указатель на них в мире. Но я никогда не удалял их в мировом классе, поэтому у меня возникали ошибки при удалении пешки и мира.

0

По вопросам рекламы [email protected]