Failed to debug
I am getting a "Debug failed" error when my program terminates. I've been trying to fix this for a long time and just can't seem to find the cause. Even my university professor said he saw nothing wrong. So, you are my last hope, stackoverllow. Please, help.
The program finds the intersection of two lists and then checks if the third list is a subset of the intersection.
Screenshot of the error:
Code:
list.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:
#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:
#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;
}
source to share
The problem is that the function list::Subset(list subset)
takes its argument by value, calling the copy list
. Since you have not followed the rule of three (as noted in Chris's comment), a shallow copy is made. This means that two instances list
"own" the pointers. When the function Subset
returns a copy, it goes out of scope, causing nodes to be removed. When the program exits the original copy it list
goes out of scope and tries to remove the same nodes that trigger the assertion again.
You can work around this by taking the argument by reference instead of value. Edit
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 create a proper copy constructor, or declare it and make it private to prevent copies from being created.
- Find out the
const
correctness. Since itSubset
doesn't change the content of the passed list, you can declare it insteadbool list::Subset(const list&) const
. This will require anlist::RetHead()
adconst
. -
bool flag
in islist::Subset
not initialized, which means that any value can be returned if your logic is wrong.
source to share