gpt4 book ai didi

c++ - 指针删除崩溃

转载 作者:太空宇宙 更新时间:2023-11-04 11:23:36 25 4
gpt4 key购买 nike

编辑:

我已经实现了复制构造函数(均来自建议的答案)。我已经在我的 Controller 类中以及它的子类中的等效版本中完成了此操作。但是,这并没有解决问题。此外,removePawn() 函数(程序中唯一调用 delete 的地方)中的计数器和控制台注释显示它仅被调用一次。

更详细地说,每个子类(不是指针)都有一个实例。这些在我的 world 类中声明。两者都通过 baseController 类指针在相同的 world 类方法中用作参数。问题是,虽然两者都以相同的顺序执行相同的进程,但如果一个类调用了 removePawn(),程序就可以正常运行,并且会持续运行。但是,如果第二个类调用了 removePawn()(专门删除),它会在该指令处使程序崩溃。

我也检查了地址。刚刚分配后的指针地址与删除时的地址相同。

更多信息:仅当玩家被杀死(删除然后给予新的 pawn)时,我才会在关闭程序时收到段错误。但是,如果程序启动然后关闭而没有超过第一个新的和最后一个删除,那么它运行得很好。

原文:

我在指针方面遇到了一些麻烦。我理解它们并相信我的代码相当健壮,但是我在调​​用这部分代码时似乎完全崩溃了。

Pawn 是一个初始化为 NULL 的 basePawn*。

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

这是 PS2 程序的大学作业,因此我的调试仅限于向控制台进行基本打印。

删除 delete 行允许主要的 new/delete 部分运行几次但是它最终也崩溃了(我假设这是因为达到了内存限制但是我不能确定)

我已经检查了所有常见的罪魁祸首,指针被初始化为 null 并且只删除了一次(也总是调用 new)。

我可能犯了一个相当明显的错误,但我不知道。任何建议都会很棒。 (如果需要,我可以发布更多代码)。

编辑:

下面是代码结构的工作原理。

basePawn 是一个具有一些代表角色的相当基本的方法的类。

Controller 是一个带有指向 basePawn(初始设置为 NULL)的指针的类,用作角色(AI 或玩家控制)的大脑。它包含一个 removePawn 方法。

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

此方法在析构函数中被调用。当 pawn 从关卡中移除时,它也会被调用。

它还有一个重生方法。

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

最佳答案

鉴于它是 PS2,我假设您无权访问 C++11 及其 -- 智能指针(std::unique_ptr 和此类)等。如果 Boost 或C++11 不是一个选项,您真的应该花时间研究如何重新实现基本的智能指针功能——这将大大减轻精神压力。但是,让我们假设这不是一个选项。

请注意这是最有可能发生的情况,因为从问题和评论中收集到的问题描述很少。

您正尝试通过在 Controller 实例超出范围时释放 pawn 等资源来利用 RAII,因为您在析构函数中调用了 removePawn —— 这很好。但是,当您不提供非平凡的复制赋值运算符和复制构造函数实现以及指针和堆分配时,类的实例可能会以多种方式丢失数据/崩溃。

您真的应该实现额外的功能来管理可能以您意想不到的方式发生的复制。如果您不自己管理它,代码可能会运行几次,并通过将 Controller 传递给函数等以某种方式复制 Controller ——它将使用旧 Controller 的数据构造一个新 Controller 。但这是一个浅拷贝,我们假设有效的 basePawn 地址将被复制,但它不会将垂死实例的地址设置为 0/NULL

在旧的超出作用域后,它的析构函数被调用。并且由于您没有使旧指针无效,它将删除现在由两个不同对象引用的同一个 pawn。当您声明 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 工具通过智能指针调查所有权透明度。编程应该是一种乐趣。

关于c++ - 指针删除崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16284262/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com