C++ 调试断言失败
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26574852/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Debug assertion failed
提问by Ivan
I get the "Debug assertion failed" error when my program ends. I've been trying to fix it for a long time and just can't find the cause. Even my prof in uni said he sees nothing wrong. So you are my last hope, stackoverllow. Please help.
当我的程序结束时,我收到“调试断言失败”错误。我已经尝试修复它很长时间了,但找不到原因。甚至我的大学教授也说他认为没有任何问题。所以你是我最后的希望,stackoverllow。请帮忙。
The program finds the intersection of two lists and then checks if the third list is a subset of the intersection.
该程序找到两个列表的交集,然后检查第三个列表是否是交集的子集。
The screenshot of the error:
错误截图:
The code:
编码:
list.h:
列表.h:
#ifndef __LIST_H_INCLUDED__
#define __LIST_H_INCLUDED__
#include <string>
#include <iostream>
#include <fstream>
struct node
{
int value;
node *next;
};
class list
{
node* head;
public:
list();
~list();
void AddNodes(std::istream &input);
void PrintList(std::ostream &output = std::cout);
void AddOneNode(int AddVal);
node* RetHead();
list* Intersection(list* list2);
bool IsPresent(int val);
bool Subset(list subset);
};
#endif
list.cpp:
列表.cpp:
#include "stdafx.h"
#include "list.h"
#include <iostream>
#include <fstream>
list::list()
{
head=NULL;
}
list::~list()
{
node* current = head;
while( current != 0 )
{
node* next = current->next;
delete current;
current = next;
}
head = 0;
}
void list::AddNodes(std::istream &input)
{
int InVal;
while(input>>InVal)
AddOneNode(InVal);
}
void list::AddOneNode(int AddVal)
{
node *NewNode= new node;
NewNode->value=AddVal;
NewNode->next=NULL;
if(!head)
head=NewNode;
else
{
node *temp=head;
while(temp->next)
temp=temp->next;
temp->next=NewNode;
}
}
void list::PrintList(std::ostream &output)
{
node *temp=head;
while(temp)
{
output<<temp->value<<std::endl;
temp=temp->next;
}
}
list* list::Intersection(list *list2)
{
list* result=new list;
node* temp1=head;
while(temp1)
{
if(list2->IsPresent(temp1->value))
result->AddOneNode(temp1->value);
temp1=temp1->next;
}
return result;
}
bool list::IsPresent(int val)
{
node *temp=head;
while(temp)
{
if(temp->value==val)
return true;
temp=temp->next;
}
return false;
}
bool list::Subset(list subset) // head=set
{
bool flag;
node* tempset=head;
node* tempsub=subset.RetHead();
while(tempset)
{
if (tempsub->value==tempset->value)
{
flag=true;
break;
}
tempset=tempset->next;
}
if (!tempset)
return false;
while(tempsub)
{
tempsub=tempsub->next;
if(!tempsub)
return true;
while(tempsub->value!=tempset->value&&tempset)
tempset=tempset->next;
if(!tempset)
return false;
}
return flag;
}
node* list::RetHead()
{
return head;
}
main.cpp:
主.cpp:
#include "stdafx.h"
#include "list.h"
#include <Windows.h>
#include <fstream>
list Cross (list list1, list list2);
bool Subset (list set, list subset);
int main()
{
setlocale (LC_ALL, "Russian");
list l1,l2,l3;
std::ifstream fl1 ("l1.txt");
std::ifstream fl2 ("l2.txt");
std::ifstream fl3 ("l3.txt");
l1.AddNodes(fl1);
std::cout<<"List 1:"<<std::endl;
l1.PrintList();
std::cout<<std::endl;
l2.AddNodes(fl2);
std::cout<<"List 2:"<<std::endl;
l2.PrintList();
std::cout<<std::endl;
l3.AddNodes(fl3);
std::cout<<"List 3:"<<std::endl;
l3.PrintList();
std::cout<<"Intersection of list 1 and list 2"<<std::endl;
list *intersec=l1.Intersection(&l2);
intersec->PrintList();
std::cout<<std::endl;
if(intersec->Subset(l3))
std::cout<<"Third set is a subset of the intersection"<<std::endl;
else
std::cout<<"Third set is not a subset of the intersection"<<std::endl;
system("pause");
return 0;
}
回答by Captain Obvlious
The problem is that the function list::Subset(list subset)
takes its argument by value causing a copy of the list
to be made. Since you did not follow the Rule of Three (as noted in Chris' comment) a shallow copyis made. This means that two instance of list
"own" the pointers. When the Subset
function returns the copy goes out of scope causing the nodes to be deleted. When the program exits the original copy of the list
goes out of scope and it attempts to delete the same nodes againcausing the assertion.
问题是该函数list::Subset(list subset)
按值获取其参数,导致生成 的副本list
。由于您没有遵循三规则(如 Chris 的评论中所述),因此制作了一个浅表副本。这意味着list
“拥有”指针的两个实例。当Subset
函数返回时,副本超出范围,导致节点被删除。当程序退出时,原始副本list
超出范围并尝试再次删除相同的节点,从而导致断言。
You can get around this by taking the argument by reference instead of by value. Change
您可以通过引用而不是值来获取参数来解决这个问题。改变
class list
{
// ... snip ...
bool Subset(list subset);
// ... snip ...
};
to
到
class list
{
// ... snip ...
bool Subset(list& subset);
// ... snip ...
};
and
和
bool list::Subset(list subset)
{
// ... snip ...
}
to
到
bool list::Subset(list& subset)
{
// ... snip ...
}
Some other suggestions:
其他一些建议:
- Either implement a proper copy constructor or declare one and make it private to prevent copies from being made
- Learn
const
correctness. SinceSubset
does not modify the contents of the list passed to it you can declare itbool list::Subset(const list&) const
instead. This will requirelist::RetHead()
to be declaredconst
as well. bool flag
inlist::Subset
is not initialized meaning that any value can be returned if your logic is not correct.
- 要么实现一个适当的复制构造函数,要么声明一个并将其设为私有以防止复制
- 学习
const
正确性。由于Subset
不会修改传递给它的列表的内容,因此您可以bool list::Subset(const list&) const
改为声明它。这也需要list::RetHead()
声明const
。 bool flag
inlist::Subset
未初始化意味着如果您的逻辑不正确,则可以返回任何值。