-1

问题:

为什么在更改我声明和使用指向对象的指针的方式后,我不断收到分段错误?

在我看来,它们似乎是随机的,但我确信有一个原因可以解释这种混乱。

简报:

几个月来,我一直在开发一款与 NetHack 非常相似的 Rogue-like 游戏,并且已经到了另一个我被卡住了好几天的地步。地牢显示,玩家可以使用 w,a,s,d 移动。当你接触到一个生物时,你开始攻击它。我一直工作到Creature <= 0。我的问题是我无法让该生物的指针恢复为空白 **Creature /NULL。有人告诉我这与我在 main.cpp 中声明指针的方式有关,所以我尝试了一些建议,现在我经常遇到段错误。由于某种原因,我大部分时间在运行游戏后甚至不能移动一次。当我可以移动时,我很好,直到生物的 HP <= 0.. 然后 seg 错误使程序崩溃。它必须是生物死亡的地方,但我花了很多时间试图调试它,调试器拒绝工作。我发誓我花了 10 到 15 个小时进行调试,没有人会让我运行我的程序!


我有一个基类Entity,它有 2 个派生类。这两个派生类是ItemCreature。这两个子类应该是不言自明的。

  • 显然Item有一些派生类,它们为Item的类型添加了更多细节。比如护甲食物武器等等。

  • 生物显然具有涉及生命体的事物。话虽如此,Creature有一个派生类Player,因为Player只能做几件事。

需要注意的一些事项:

  • 我使用工厂方法模式,它返回指向Creatures的指针和另一个指向Items的指针。我现在只专注于生物

  • main.cpp我创建了一个Player对象。然后我创建了 3 个指向Creatures的指针,这是分段错误开始发生的位置/时间。这是我在更改它之前的方式,然后是我如何更改它。

    Creature * pCreature1 = NULL;
    Creature * pCreature2 = NULL;
    Creature * pCreature3 = NULL;
    

至:

    Creature * pCreature1 = new Creature();
    Creature * pCreature2 = new Creature();
    Creature * pCreature3 = new Creature();

第一种方法让我按预期做所有事情,直到需要将生物从关卡中移除。由于人们告诉我我使用错误的指针,我将其更改为第二种方式。

代码:

我将添加一些我认为可能出现问题的代码。但是,我已经两次发布了这个问题,每个人都抨击我提供了太多的代码,然后又没有足够的代码。希望能满足每个人,并让这比我说的压倒性的听起来更容易,我会在哪里发布Creature死在这里。我已将所有内容上传到 Cloud 9,以便每个人都可以查看我当前状态的文件并运行程序以查看所有错误的位置。

使用这些指针并可能导致我认为错误的类是:

  • 主文件
  • 生物
  • 播放器
  • 地牢等级

我尽量不让我听起来像我希望有人“给我答案”,但最近两次我问了基本相同的任务,每个人都指责我。我尝试调试,但我的 Mac 上的任何调试器都不会更新。前几天晚上我花了几个小时尝试这个。您可以在这里看到:为什么 c++ 标准库不起作用?

这真的不应该是一个复杂的问题。我被困在一个点上,我做的任何事情都不会减少错误:(

任何想法、提示和建议将不胜感激。

这是我的 cloud 9 项目的链接: http: //c9.io/moddedlife/jhackpublic

此页面上的所有其他内容都是代码片段。再次感谢!

玩家攻击方法:

void Player::attack(Creature * monster, Creature * player, std::mt19937 & randomGen,     DungeonLevel & dl){
    int monsterHit = monster->getHit(randomGen);
    int playerHit = getHit(randomGen);

    if ((monster->getHP() - playerHit) <= 0){
            playerHit = monster->getHP();
            cout << "Monster name: " << monster->getName() << endl;
            delete monster;
            monster = NULL;
            cout << "Monster name after: " << monster->getName() << endl;
    }
    else if ((player->getHP() - monsterHit) <= 0){
            monsterHit = player->getHP();
            //game over
    }

    cout << "You hit: " << playerHit << endl;
    player->setHP((player->getHP() - monsterHit));
    player->addXp(playerHit);

    if (monster != NULL){
            cout << "Monsters Hit: " << monsterHit << endl;
            monster->setHP((monster->getHP() - playerHit));
            cout << "Your HP: [" << player->getHP() << "]/[" << player->getMaxHP() << "]" << endl;
            cout << "Monsters HP: [" << monster->getHP() << "]/[" << monster->getMaxHP()     << "]" << end$
    }
    else {
            cout << "you Killed it!" << endl;
    }
    return;
}

玩家移动方法:

我打算把所有这些代码,但它本质上是相同的——只有方向改变..每个方向大约是 30-50 行。您可以在此处查看我的任何文件的所有代码:http: //c9.io/moddedlife/jhackpublic

如果不允许使用 cloud 9 或其他什么,我将在此处添加代码。我只是认为这比从多个文件中粘贴块要容易得多。

谢谢

4

2 回答 2

1

首先,重要的是要了解分段错误是什么以及导致它们的原因。我并不是要指责你也不知道,但如果你不知道,维基百科页面有一些不错的信息:

分段错误...通常是尝试访问 CPU 无法物理寻址的内存。(http://en.wikipedia.org/wiki/Segmentation_fault

有很多不同的方法可以导致段错误,但最常见的(无论如何我认为......我应该说我最大的段错误来源)方法是取消引用空指针(或删除/释放指针)。

从您发布的代码的快速查看来看,我看到了这一点:

delete monster;
monster = NULL;
cout << "Monster name after: " << monster->getName() << endl;

请记住,一旦删除(或释放)任何已分配的内存块,就不应尝试访问它。通过调用monster->getName(),您正在取消引用(现在)NULL 指针——这通常会导致非常温和但可怕的分段错误。

我不能保证这是唯一有问题的行(毕竟,我只看了你发布的几个片段),但它应该是一个开始,希望你知道在你的代码中寻找什么。

于 2013-04-28T01:40:14.017 回答
0

这对我来说太长了,无法找到确切的问题,但是delete如果怪物死了,它似乎很可疑。我推荐两件事:让“死”成为怪物的状态,并使用智能指针。根本不需要处理 NULL 情况或删除。

于 2013-04-28T01:28:05.060 回答