我正在为我的软件工程课制作一个游戏,我的小组遇到了一个奇怪的问题。我们在级别中创建项目作为双重链接列表,并且一触摸我们在该项目上调用删除的项目。但是当我触摸链表中itemHead指向的项时,我得到一个损坏的双链表错误。由于某种原因,itemHead接下来似乎指向一些垃圾内存。
如果它出现在每台机器上都不会那么奇怪,但它似乎只发生在我组中的一些笔记本电脑上。我们都比较了我们的规格,我们都运行64位linux铸币,我们都有相同版本的g ++,我们都从gitHub做了一个新的克隆,所以我们都有相同版本的游戏。我们似乎无法理解为什么仅在某些机器上发生了段错误。
如果您想查看代码,请发布您的gitHub帐户名称,我们将为您提供访问权限。但只是说明为什么会发生这种情况应该指出我们正确的方向来弄清楚这是如何搞乱的。
以下是我们如何在循环双联链表中创建项目,检测项目与角色的碰撞以及我们如何删除。按此顺序。
Items *createDiamond() {
Items *it = new Diamond;
it->next = itemHead;
if (itemHead != NULL)
itemHead->prev = it;
itemHead = it;
nItems++;
return it;
}
void checkItemCollision(Game * g) {
Items *item = g->itemHead;
while(item!=NULL) {
int itemY = item->getCenterY();
int itemX = item->getCenterX();
int itemH = item->getHeight();
int itemW = item->getWidth();
//top
if ( (g->player.getPosX() + g->player.getWidth() > itemX
&& g->player.getPosX() -g->player.getWidth() < itemX )
&& (g->player.getPosY() - g->player.getHeight() <= itemY )
&& (g->player.getPosY() + g->player.getHeight() >= itemY) )
{
if (item->type == "diamond") {
g->player.addToScore(500);
} else if (item->type == "heart") {
g->player.addToScore(200);
g->player.incHealth();
}
if (item->type == "dagger"){
g->player.setDagActive();
g->player.hasDaggers = true;
g->player.daggers =+ 7;
}
if (item->type == "axe"){
g->player.setAxeActive();
g->player.hasAxes = true;
g->player.axes =+ 7;
}
Items *saveItem = item;
g->deleteItem(item);
item = saveItem;
}
item = item->next;
}
}
void deleteItem(Items *node) {
if(node->prev == NULL){enter code here`
if (node->next == NULL){
itemHead = NULL;
}
else {
node->next->prev = NULL;
itemHead = node->next;
}
}
else {
if (node->next == NULL){
node->prev->next = NULL;
}
else {
node->prev->next = node->next;
node->next->prev = node->prev;
}
}
free(node);
nItems--;
node = NULL;
}
答案 0 :(得分:0)
访问未初始化的内存可能会导致这些效果。通常在C ++标准中,这是由&#34;未识别的行为&#34;指定的,所以一切都可能发生,从正常工作到seg-faults。我建议你通过内存验证器开始你的程序.. Valgrind似乎是个好人选。
答案 1 :(得分:0)
我看到的一个错误是:
Items *it = new Diamond;
然后在deleteItem
函数中执行此操作:
free(node);
其中node
的类型为Item*
。
您正在混合分配和释放例程。使用new
分配时,您必须使用delete
,而不是free
。您对free
系列(malloc
,malloc
,calloc
等中的功能使用realloc
。通过混合分配/解除分配例程,您在应用程序中引入了未定义的行为。
那条线应该是这样的:
delete node
现在即使进行了更改,也许并不能保证您的程序能够正常运行。如果您犯了这样的错误,很可能您的代码可能还有其他问题。
例如,这可能有几个问题:
if (item->type == "diamond")
和类似的行。
如果type
是std::string
,那么它就可以了(当你拨打free
而不是delete
时,可能是你的段错误的原因)。如果它是动态分配的char *
,那么这不仅仅是将char数组进行比较的错误方法,那么Item
类型可能不会跟随rule of 3
,因此如果在副本中使用,则会导致未定义的行为。
可能导致问题的另一个问题:
Items *it = new Diamond;
现在,假设Diamond
来自Items
,并且由于您要删除Items
(即使您的原始代码有误),Items
类必须声明一个虚拟析构函数(即使它是一个空虚拟析构函数)。
原因是您(或将要)使用delete
指针调用Items
,这是基类。如果基类没有虚拟析构函数,则(再次)未定义行为通过派生类在基类指针上发出对delete
的调用。因此,请确保Items
具有虚拟析构函数。