带有链接列表的奇怪段错误

时间:2018-11-05 19:23:06

标签: c++

在Visual Studios上使用此最新版本的软件时,尝试使用makefile将其发送到学校服务器,并且在尝试将int添加到空列表时,valgrind上的此错误在进程第一个headPtr == nullptr处停止了

segfault

它说要添加一些更多的细节,所以我想我会一直写直到它让我提交为止,我不知道还有什么要说的,如果有人想尝试一下,我有菜单和有效的驱动程序功能,但是测试可以淘汰他们。

#include "list.hpp"

int main()
{
    menu();
}
list: main.o list.o valid.o menu.o  node.o  
    g++ -std=c++0x -g main.o list.o valid.o menu.o  node.o   -o list
main.o: main.cpp
    g++ -std=c++0x -g -c main.cpp
node.o: node.cpp 
    g++ -std=c++0x -g -c node.cpp

list.o: list.cpp
    g++ -std=c++0x -g -c list.cpp


menu.o: menu.cpp 
    g++ -g -std=c++0x -c menu.cpp

valid.o: valid.cpp 
    g++ -g -c -std=c++0x valid.cpp
clean:
    rm *.o list

valgrind错误enter image description here

  [1]: https://i.stack.imgur.com/MM9az.png



#include"list.hpp"


List::List()
{
    Node* headPtr = nullptr;
    Node* tailPtr = nullptr;
}
List::~List()
{

    if (headPtr != nullptr)

    {
        while (headPtr != nullptr)
        {
            Node* toDel = headPtr;
            headPtr = headPtr->getNext();
            delete toDel;
        }
    }
 }

void List::addHead(int add)
{

    Node* nodePtr = new Node;
    Node* nll = nullptr;
    nodePtr->setVal( add);//put in data
    nodePtr->setPrev(nll); // always do ->make prev( before new head) null as is now new head
    if (headPtr == nullptr)//empty list
    {
        nodePtr->setNext(nll);//nothing next prev already null

        headPtr = nodePtr;//only node set head
        tailPtr = nodePtr;//set tail
    }
    else //nodes exists already
    {
        nodePtr->setNext(headPtr);//next of new head is old head 
        (headPtr)->setPrev(nodePtr); //prev old head new haed
        headPtr = nodePtr;//change headPtr
    }

    traverse();

}

void List::addTail(int add)//takes pointer to pointer to tail node
{
    Node* nll = nullptr;

    Node* nodePtr = new Node;
    nodePtr->setNext(nll);//will be last node
    nodePtr->setVal(add);//put in data
    if (tailPtr == nullptr)
    {
        headPtr = nodePtr;//only node set head
        tailPtr = nodePtr;
        nodePtr->setPrev(nll); //nothing there
    }
    else
    {
        nodePtr->setPrev(tailPtr);
        tailPtr->setNext(nodePtr);
        tailPtr = nodePtr;
    }
    traverse();

}
    /*if (headPtr != NULL)//if this is NOT first element added

{//then stick new node to beginning of list b4 swaping head

    (headPtr)->setPrev(nodePtr);
}
headPtr = nodePtr; //reset head to new node

if (tailPtr == NULL)
{
    tailPtr = nodePtr;//if first node set tail


}*/
    /*
        tailPtr->setNext(nodePtr) ;//make link to old tail ->newtail
    }
    tailPtr = nodePtr;
    if (headPtr == NULL)
    {
        headPtr = nodePtr;//set head if first ele
    }*/






void List::delFirst()
{
    Node* nll = nullptr;

    if (headPtr == nullptr)
    {
        std::cout << "The list was already empty." << std::endl;
    }
    else if (headPtr->getNext() == nullptr || tailPtr->getPrev()== nullptr)//one node only
    {
        delete headPtr;
        headPtr = nullptr;
        tailPtr = nullptr;
    }
    else
    {
        //Node* tmp = headPtr;
        headPtr = (headPtr)->getNext();
        delete headPtr->getPrev();
        headPtr->setPrev(nll);
    }
    traverse( );

}
void List::delLast( )
{
    Node* nll = nullptr;

    if (tailPtr == nullptr)//empty
    {
        std::cout << "The list was already empty." << std::endl;
    }
    else if (headPtr->getNext() == nullptr || tailPtr->getPrev() == nullptr)//one node only?
    {
        delete tailPtr;
        headPtr = nullptr;
        tailPtr = nullptr;
    }
    else
    {   
        tailPtr = (tailPtr)->getPrev();//move back one
        delete  tailPtr->getNext();
        tailPtr->setNext(nll);

    }
    traverse();

}

void  List::reverseTrav()
{
    Node* tmp = tailPtr;
    if (tmp == nullptr)
    {
        std::cout << "The list is empty." << std::endl;

    }
    while (tmp != nullptr)
    {
        std::cout << tmp->getVal() << " " ;
        tmp = tmp->getPrev();
    }
    std::cout << std::endl;
}
void  List::traverse()
{
    Node* tmp = headPtr;
    if (tmp == nullptr)
    {
        std::cout << "The list is empty." << std::endl;

    }
    while (tmp != nullptr)
    {
        std::cout << tmp->getVal() << " " ;
        tmp = tmp->getNext();
    }

    std::cout << std::endl;
}
void menu()
{
    List list;


    Menu myMenu;

    myMenu.addItem("Enter 1 to add integer to front\nEnter 2 to add integer to back \nEnter 3 to delete from front \nEnter 4 to delete from back \nEnter 5 to traverse in reverse \n Enter 6 to quit");//itm 1
    myMenu.addItem("enter integer to add to front (limits +/-1000000)");//item 2
    myMenu.addItem("enter integer to add to back (limits +/-1000000)");//item 3;
    //myMenu.addItem("enter number:");//item 4;
    //myMenu.addItem("enter number to find triangle value from");//item 5;
    bool play = true;

    do
    {
        myMenu.displayChoice(1);
        int choice = myMenu.getIntAnswer(1, 5);
        if (choice == 1)
        {
            myMenu.displayChoice(2);
            int ans = myMenu.getIntAnswer(-1000000, 1000000);
            list.addHead(ans);
        }
        else if (choice == 2)
        {

            myMenu.displayChoice(3);
            std::cout << "upper and lower limits of numbers to be summed -100000000 and 100000000" << std::endl;
            int ans = myMenu.getIntAnswer(-1000000, 1000000);
            list.addTail(ans);
        }
        else if (choice == 3)
        {
            list.delFirst();

        }
        else if (choice == 4)
        {

            list.delLast();
        }
        else if (choice == 5)

        {
            list.reverseTrav();
        }
        else if (choice == 6)
        {
            play = false;
        }
    } while (play == true);

}


#ifndef LIST_HPP
#define LIST_HPP

#include "node.hpp"

class List
{
private:
    Node *headPtr;
    Node *tailPtr;
public:
    List();
    void addHead( int);
    void addTail( int);
    void delFirst();
    void delLast();
    void reverseTrav();
    void traverse();
    ~List();
};
void menu();

#endif
#ifndef NODE_HPP
#define NODE_HPP
#include <iostream>
#include "menu.hpp"
class Node
{
private:
    Node * next;
    int val;
    Node * prev;
public:
    Node * getPrev();
    Node * getNext();
    void setNext(Node*);
    void setPrev(Node*);
    int getVal();
    void setVal(int);
};

#endif
#include "node.hpp"
Node * Node::getPrev()
{
    return prev;
}
Node * Node::getNext()
{
    return next;
}
void Node::setNext(Node* nIn)
{
    next = nIn;
}
void Node::setPrev(Node* pIn)
{
    prev = pIn;
}

int Node::getVal()
{
    return val;
}
void Node::setVal(int vIn)
{
    val = vIn;
}

1 个答案:

答案 0 :(得分:3)

Valgrind试图告诉您答案!如果您看到过:

  

有条件的跳跃或移动取决于未初始化的值

几乎可以肯定您做错了什么。在这种情况下,Valgrind谈论的是:

if (headPtr == nullptr)//empty list

但是您初始化了headPtr ...不是吗?让我们看看您的构造函数:

List::List()
{
    Node* headPtr = nullptr;
    Node* tailPtr = nullptr;
}

哦,哦!您创建了两个新的Node*并将它们设置为nullptr,但是您从不修改班级的headPtrtailPtr成员!请记住,在C ++中,您可以通过在子作用域中声明一个具有相同名称的新变量来轻松隐藏变量。

Node*放到构造函数中,这样您就可以实际初始化成员变量,或者甚至更好的方法是使用字段初始化列表,这样您甚至不必担心这一点!

List::List() : headPtr(nullptr), tailPtr(nullptr) { }