1

SDLを使用してゲームを作成しようとしていますが、奇妙なセグフォールトがたくさん発生しています。

クラスCreatureからパブリック変数を取得するクラスMonsterとPlayerを作成しました。クラスCreatureは、クラスObjectから変数を取得します。ちょうどそのように:

class Object {
public:
    Area* area_pointer; // Pointer to an Area in which object is present.
    Sprite sprite; // Class that has SDL_Surface* and some other things.
    Animation animation; // nothing usefull
    int ID;
    short int position_x; // nothing usefull
    short int position_y; // nothing usefull
    short int effect_x; // nothing usefull
    short int effect_y; // nothing usefull
    .... //Some functions that are not important right now.
};

クラススプライト:

class Sprite {
public:
    SDL_Surface* image;
    short int x;
    short int y;
    short int w;
    short int h;
    Sprite ()
    {
        image = NULL;
        x = 0;
        y = 0;
        w = 0;
        h = 0;
    }   
};

クラスクリーチャー、プレイヤー、モンスター:

class Creature : public Object {
        public:
            char move_direction;
            char speed; 
            ..// Some not important functions.
};
class Player : public Creature {
        public:
            char select_type;
            int select_ID;
            std::vector <Item> equip;
            std::vector <Item> inventory;
            std::vector <Effect> effects;
            Player (Area* c_area_pointer, int data [])
            {
                area_pointer = c_area_pointer;
                sprite.image = SurfaceLoad ("Images/Players/" + IntToString (data [0]) + ".png");
                sprite.x = 0;
                sprite.y = 0;
                sprite.w = 0;
                sprite.h = 0;
                ID = data [0];
                position_x = data [1];
                position_y = data [2];
                effect_x = 0;
                effect_y = 0;
            }
            ~Player ()
            {
                SDL_FreeSurface (sprite.image);
                .....
            }
};
class Monster : public Creature {
        public:
            char type;
            std::vector <Item> loot;
            std::vector <Effect> effects;
            Monster (Area* c_area_pointer, int data [])
            {
                area_pointer = c_area_pointer;
                sprite.image = SurfaceLoad ("Images/Monsters/" + IntToString (data [3]) + ".png");
                sprite.x = 0;
                sprite.y = 0;
                sprite.w = 0;
                sprite.h = 0;
                ID = data [0];
                position_x = data [1];
                position_y = data [2];
                effect_x = 0;
                effect_y = 0;
                type = data [3];
            }
            ~Monster ()
            {
                SDL_FreeSurface (sprite.image);
                .....
            }
};

SurfaceLoad関数:

SDL_Surface* SurfaceLoad (std::string file_name)
{
SDL_Surface* surface_1 = NULL;
SDL_Surface* surface_2 = NULL;
surface_1 = IMG_Load (file_name.c_str ());
surface_2 = SDL_DisplayFormat (surface_1);
if (surface_1 != surface_2) SDL_FreeSurface (surface_1); // This line may be strange to some of you, but it is related to other error i had in past.
SDL_SetColorKey (surface_2, SDL_SRCCOLORKEY, 0xFFFFFF);
return surface_2;
}

txtファイルからデータをロードし、それに基づいてオブジェクトを作成しようとしています。私はそれに独自のLoad関数を使用します。次に、クラスオブジェクトへのポインタを作成します。

        Player* player;
        std::string players_name = save_name + "Areas/" + IntToString (ID) + "/players.txt"; //Path to the file cointaining players data.
        std::ifstream players_file;
        players_file.open (players_name.c_str ());
        Monster* monster;
        std::string monsters_name = save_name + "Areas/" + IntToString (ID) + "/monsters.txt"; //Path to the file cointaining monsters data.
        std::ifstream monsters_file;
        monsters_file.open (monsters_name.c_str ());

次に、テキストファイルからデータをロードし、それをfile_dataという名前のintの配列に配置し、それに基づいて新しいクラスオブジェクトを作成します。

        while (!players_file.eof ())
        {
            getline (players_file, file_text);
            while (file_text [data_position_2 + 1] != ';')
            {
                data_position_2 = file_text.find (",", data_position);
                data.assign (file_text, data_position, data_position_2 - data_position);
                file_data [data_index] = atoi (data.c_str ());
                data_position = data_position_2 + 1;
                data_index++;
            }
            player = new Player (this, file_data);
            this->area_map.players.push_back (*player); //Vector players inside object area_map which contain also monsters vector. "this" is a pointer to object that contain Load function and area_map object.
            delete player;
            data_index = 0;
            data_position = 0;
            data_position_2 = 0;
        }

コードのこの部分は機能しますが、monsters_fileとmonsters vectorでまったく同じことを行うと、多くの奇妙なエラーが発生しました。私が得た最初のエラーは、データポインタをベクトルにプッシュした後にポインタを削除するときのセグメンテーション違反でした。それを確認したところ、SDL_FreeSurface()を呼び出すと、deconstructorでプログラムがクラッシュ(segfault)することがわかりました。そこで、コンストラクターがサーフェスを正しくロードするかどうかを確認しました。オブジェクトの作成はすべて問題ないことがわかりましたが、SurfaceLoad()を呼び出すと、突然クラッシュ(segfault)が発生し始めました。この関数もチェックし、すべてが問題ありませんでした。サーフェスへのポインターは問題なく、返されるポインターは問題ありませんでしたが、何らかの理由で次の場所でクラッシュしました。

sprite.image = SurfaceLoad (...);

理由もなく、ここでクラッシュが停止してからしばらく経ちました(私はその行を追加しました

if (surface_1 != surface_2) SDL_FreeSurface (surface_1);

、SDL_DisplayFormat()がフォーマットされていないサーフェスへのポインターと同じポインターを返すことがあることに気付いたためです。)ベクトルへのポインターが指すオブジェクトをpush_backすると、クラッシュし始めました(segfaultも)。

this->area_map.monsters.push_back (*monster);

ゲーム作成のこの段階では、モンスターとプレイヤーのクラスはほとんど同じなので、なぜ問題なくプレイヤーが作成されるのかわかりません。また、モンスターの作成には多くの問題があります。誰かがそれを修正する方法を知っていますか?

4

1 に答える 1

1

少しまとまりがないように見えるコードがたくさんあります。たとえば、PlayerデストラクタがSpriteで宣言されている画像を解放するのはなぜですか?それはスプライトデストラクタの仕事ではありませんか?そして、なぜすべてが公開されているのですか?しかし、とにかくあなたが説明する症状から、それは三つのルールに従わないという典型的なケースのように聞こえます。

メモリまたはその他のリソースを内部で割り当てるクラス(Spriteのイメージポインタなど)を作成する場合は、割り当てられたメモリまたはリソースを正しく処理するコピーコンストラクタと割り当て演算子を作成する必要があります。そうしないと、このようなエラーが発生します。

三つのルールに関するいくつかの重要な情報については、ここを参照してください。このことを理解していない場合は、常にバグのあるC++コードを記述していることになります。リソースの管理に関するセクションはあなたにとって最も関連性がありますが、すべてを読んでください。

于 2012-10-28T15:27:47.987 に答える