A asserção de depuração foi mal-sucedida

recebo o erro "a asserção de depuração falhou" quando o meu programa termina. Estou a tentar arranjá-lo há muito tempo e não consigo encontrar a causa. Até o meu professor da universidade disse que não vê nada de errado. Então és a minha última esperança, stackoverllow. Ajudar.

o programa encontra a intersecção de duas listas e depois verifica se a terceira lista é um subconjunto da intersecção.

A imagem do erro:

Here

A código:

lista.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

lista.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;
}
Author: Ivan, 2014-10-26

1 answers

O problema é que a função list::Subset(list subset) toma o seu argumento pelo valor, fazendo com que uma cópia do list seja feita. Uma vez que você não seguiu a regra de três (como anotado no Comentário de Chris) a cópia rasa é feita. Isto significa que duas instâncias de list "possuem" os ponteiros. Quando a função Subset devolve a cópia sai do âmbito, fazendo com que os nós sejam apagados. Quando o programa sai da cópia original do list sai do âmbito e tenta apagar os mesmos nós Mais uma vez causa a afirmação.

Você pode contornar isso tomando o argumento por referência em vez de por valor. Variação

class list
{
    // ... snip ...
    bool Subset(list subset);
    // ... snip ...
};

A

class list
{
    // ... snip ...
    bool Subset(list& subset);
    // ... snip ...
};

E

bool list::Subset(list subset)
{
    // ... snip ...
}

A

bool list::Subset(list& subset)
{
    // ... snip ...
}

Algumas outras sugestões:

  1. ou implementa um construtor de cópias adequado ou declara-o e torna-o privado para impedir que as cópias sejam feitas
  2. aprende const a correcção. Dado que Subset não modifica o conteúdo da lista que lhe foi passada a si em vez disso, posso declará-lo. Isto exigirá list::RetHead() que também seja declarado const.
  3. bool flag in list::Subset is not initialized meaning that any value can be returned if your logic is not correct.
 7
Author: Captain Obvlious, 2014-10-26 16:20:02