-1

質問:

オブジェクトへのポインターを宣言および使用する方法を変更した後、セグメンテーション違反が発生し続けるのはなぜですか?

私の意見では、それらはランダムに見えますが、この混乱を説明する理由があると確信しています.

ブリーフィング:

私は、NetHack に非常によく似た Rogue のようなゲームに数か月取り組んできました。ダンジョンが表示され、プレーヤーは w、a、s、d を使用して移動できます。クリーチャーと接触すると、攻撃を開始します。Creature <= 0のポイントまでこれを機能させました。私の問題は、そのクリーチャーのポインターを空白の **Creature /NULLに戻すことができないことでした。main.cpp でポインターを宣言した方法に関係があると言われたので、いくつかの提案を試してみたところ、セグ フォールトが常に発生するようになりました。ほとんどの場合、ゲームを実行した後、何らかの理由で一度も移動できません。私が動くことができるとき、私は生き物まで良いですの HP <= 0.. の場合、seg fault によりプログラムがクラッシュします。クリーチャーが死ぬ場所でなければなりませんが、デバッグに多くの時間を費やしたため、デバッガーは動作を拒否していました。デバッグに 10 ~ 15 時間費やしましたが、誰もプログラムを実行させてくれませんでした。


2 つの派生クラスを持つ基本クラスEntityがあります。これら 2 つの派生クラスはItemCreatureです。これら 2 つのサブクラスは一目瞭然です。

  • 明らかに、 Itemには、 Itemのタイプの詳細を追加する派生クラスがいくつかあります。食べ物武器など..

  • 生き物は明らかに、生命に似た実体を含むものを持っています。そうは言っても、Creatureには派生クラスPlayerがあります。これは、 Playerができることはあとわずかしかないためです。

注意事項:

  • CreaturesへのポインターとItemsへの別のポインターを返すFactory メソッド パターンを使用します。私は今クリーチャーに集中しています。

  • main.cppで、単一のPlayerオブジェクトを作成します。次に、Creaturesへの 3 つのポインターを作成します。これは、セグメンテーション違反が発生し始めた場所/時期です。変更前の状態と、その後の変更方法を以下に示します。

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

に:

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

最初の方法では、クリーチャーをレベルから削除する必要があるまで、期待どおりにすべてを実行できました。ポインターの使い方が間違っていると言われたので、2 番目の方法に変更しました。

コード:

問題が発生している可能性があると思われるコードをいくつか追加します。しかし、私はこの質問を他に 2 回投稿しましたが、提供するコードが多すぎてコードが不十分であると、誰もが私を非難しました。ここで死ぬ。Cloud 9 にすべてをアップロードしたので、誰もが私のファイルを現在の状態で表示し、プログラムを実行してすべての障害がどこにあるかを確認できます。

これらのポインターを使用し、私が信じている障害を引き起こしている可能性のあるクラスは次のとおりです。

  • main.cpp
  • 生き物
  • プレーヤー
  • タイル
  • ダンジョンレベル

誰かに「答えてもらいたい」と思われないようにしているのですが、過去 2 回は本質的に同じクエストを尋ねたので、誰もが私を非難しています。デバッグを試みましたが、Mac のデバッガーが更新されません。私は先日、これを試すのに何時間も費やしました。ここで確認できます: c++ 標準ライブラリが機能しないのはなぜですか?

これは、それほど複雑な問題ではないはずです。私はある時点で動けなくなり、何をしてもエラーが減りません:(

考え、ヒント、提案をいただければ幸いです。

これが私のクラウド 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

クラウド 9 の使用が許可されていないなどの場合は、ここにコードを追加します。複数のファイルからブロックを貼り付けるよりもはるかに簡単になると思いました。

ありがとう

4

2 に答える 2

1

まず、セグメンテーション違反とは何か、およびその原因を理解することが重要です。どちらも知らないと非難するつもりはありませんが、知らない場合は、ウィキペディアのページに適切な情報があります。

セグメンテーション違反 ... 通常、CPU が物理的にアドレス指定できないメモリにアクセスしようとする試みです。( http://en.wikipedia.org/wiki/Segmentation_fault )

セグメンテーション違反を引き起こす方法はたくさんありますが、最も一般的な方法は (とにかく私の意見では... セグメンテーション違反の最大の原因であると言うべきです) 方法は、null ポインター (または削除/解放されたポインター) を逆参照することです。

あなたが投稿したコードをざっと見て判断すると、次のようになります。

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

割り当てられたメモリ ブロックを削除 (または解放) したら、そのブロックにアクセスしてはならないことに注意してください。呼び出すmonster->getName()ことにより、(現在) NULL ポインターを逆参照しています。これにより、通常、穏やかではあるが恐ろしいセグメンテーション違反が発生します。

これが唯一の問題のある行であるとは約束できません (結局のところ、投稿されたいくつかのスニペットしか見ませんでした)。

于 2013-04-28T01:40:14.017 に答える