C++ 奇怪的分割错误-将指针指向向量的对象推回会导致崩溃
我试图用SDL写一个游戏,但是我遇到了很多奇怪的错误 我已经创建了类怪物和玩家,它们从类生物中获取公共变量。类从类对象获取变量。就这样,C++ 奇怪的分割错误-将指针指向向量的对象推回会导致崩溃,c++,pointers,vector,segmentation-fault,sdl,C++,Pointers,Vector,Segmentation Fault,Sdl,我试图用SDL写一个游戏,但是我遇到了很多奇怪的错误 我已经创建了类怪物和玩家,它们从类生物中获取公共变量。类从类对象获取变量。就这样, 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. Animati
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);
.....
}
};
我尝试从txt文件中加载数据,并在此基础上创建对象。我使用自己的加载函数来实现这一点。它创建指向类对象的指针,例如:
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 ());
然后,它从文本文件加载数据,并将其放入int命名的file_data数组中,并基于该数组创建新的类对象
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_文件和monsters vector执行完全相同的操作会导致许多奇怪的错误。我得到的第一个错误是segfault,在将数据指针按到向量后删除指针。我检查了一下,发现解构器调用SDL_FreeSurface()时程序崩溃(segfault)。所以我检查了我的构造函数是否正确加载了surface。我发现构造一个对象一切正常,但是当调用SurfaceLoad()时,它突然开始崩溃(segfault)。也检查了这个函数,一切都正常:指向曲面的指针正常,它返回的指针正常,但由于某种原因,它在以下位置崩溃:
sprite.image = SurfaceLoad (...);
一段时间后,它停止在这里崩溃,没有任何原因(我只是添加了这一行)
if (surface_1 != surface_2) SDL_FreeSurface (surface_1);
,因为我注意到SDL_DisplayFormat()有时返回与指向未格式化曲面的指针相同的指针。),并且在我将指针指向向量的对象推回时开始崩溃(segfault也是):
this->area_map.monsters.push_back (*monster);
怪物和玩家类在创建游戏的这个阶段几乎是一样的,所以我不知道为什么它创建玩家没有任何问题,而且它在创建怪物方面有很多问题。有人知道如何解决这个问题吗?大量的代码看起来有点杂乱无章。例如,为什么玩家析构函数释放在Sprite中声明的图像?这不是精灵毁灭者的工作吗?为什么一切都是公开的?但不管怎样,从你描述的症状来看,这听起来像是一个典型的不遵守三原则的案例 在编写内部分配内存或其他资源的类(如Sprite中的图像指针)时,必须编写正确处理分配内存或资源的复制构造函数和赋值运算符。如果你不这样做,你就会犯这样的错误
请参阅,以了解有关三原则的一些基本信息。如果你不理解这些东西,那么你将总是编写Bugy C++代码。关于管理资源的部分与您最相关,但请通读。很好地加载了看起来有点杂乱无章的代码。例如,为什么玩家析构函数释放在Sprite中声明的图像?这不是精灵毁灭者的工作吗?为什么一切都是公开的?但不管怎样,从你描述的症状来看,这听起来像是一个典型的不遵守三原则的案例 在编写内部分配内存或其他资源的类(如Sprite中的图像指针)时,必须编写正确处理分配内存或资源的复制构造函数和赋值运算符。如果你不这样做,你就会犯这样的错误
请参阅,以了解有关三原则的一些基本信息。如果你不理解这些东西,那么你将总是编写Bugy C++代码。关于管理资源的部分与您最相关,但请通读。非常感谢您的回答。我为类Monster创建了复制构造函数,现在它可以工作了,所以我现在要为每个类创建这些构造函数。似乎我要学的比我想象的还要多,但无论如何,再次感谢并为发布这么多代码感到抱歉。我只想发布您需要的所有内容。@Mittorn代码太多总比代码太少好。您不需要为每个类编写这些构造函数,只需要那些显式管理资源的构造函数。在写“我将为每一个类创建这些构造函数”时,我想到的是每一个类都是以与玩家类似的方式加载的。非常感谢你的回答。我为类Monster创建了复制构造函数,现在它可以工作了,所以我现在要为每个类创建这些构造函数。似乎我要学的比我想象的还要多,但无论如何,再次感谢并为发布这么多代码感到抱歉。我只想发布您需要的所有内容。@Mittorn代码太多总比代码太少好。您不需要为每个类编写这些构造函数,只需要那些显式管理资源的构造函数。在写“我将为每个类创建这些构造函数”时,我考虑的是以与玩家类似的方式加载的每个类。
this->area_map.monsters.push_back (*monster);