【问题标题】:Debug assertion failed调试断言失败
【发布时间】:2014-10-26 15:52:24
【问题描述】:

我的程序结束时出现“调试断言失败”错误。我已经尝试修复它很长时间了,但找不到原因。甚至我在大学的教授也说他认为没有错。所以你是我最后的希望,stackoverllow。请帮忙。

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

错误截图:

代码:

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

ma​​in.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;
}

【问题讨论】:

  • 您的包含保护使用reserved identifier。您也没有遵循三原则(真的,不要使用拥有原始指针)。
  • 你的输入数据是什么?
  • 你很可能会“双重释放”某些东西。
  • @chris 虽然是真的,但我认为这不是原因,因为如果你的名字足够独特,冲突的可能性几乎是 0
  • @Creris,我不认为这是原因,但这肯定不是一个好主意。

标签: c++ debugging linked-list


【解决方案1】:

问题在于函数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&amp;) const。这也需要将 list::RetHead() 声明为 const
  3. list::Subset 中的 bool flag 未初始化,这意味着如果您的逻辑不正确,则可以返回任何值。

【讨论】:

    猜你喜欢
    • 2015-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多