调试断言失败

时间:2014-10-26 15:52:24

标签: c++ debugging linked-list

我得到"调试断言失败"我的程序结束时出错。我一直在努力修复它并且无法找到原因。甚至我在大学的教授说他没有看错。所以你是我最后的希望,stackoverllow。请帮忙。

程序找到两个列表的交集,然后检查第三个列表是否是交集的子集。

错误的屏幕截图:

Here

代码:

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;
}

1 个答案:

答案 0 :(得分:7)

问题是函数list::Subset(list subset)通过值获取其参数,从而导致list的副本生成。由于您没有遵循三条规则(如Chris的评论中所述),因此制作了浅层副本。这意味着list的两个实例“拥有”指针。当Subset函数返回时,副本超出范围,导致节点被删除。当程序退出list的原始副本超出范围时,它会尝试再次删除的相同节点,从而导致断言。

你可以通过引用而不是值来获取参数。改变

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

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

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

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

其他一些建议:

  1. 要么实现正确的复制构造函数,要么声明一个并将其设为私有以防止复制
  2. 了解const正确性。由于Subset不会修改传递给它的列表的内容,因此您可以将其声明为bool list::Subset(const list&) const。这也需要list::RetHead()声明const
  3. bool flag中的
  4. list::Subset未初始化,这意味着如果您的逻辑不正确,则可以返回任何值。