单链表 - 分段错误

时间:2018-03-10 16:01:14

标签: c++ linked-list singly-linked-list

首先,抱歉长代码。我尽力把它修剪得尽可能小。 当我想在我的单链表(在SLList.hxx中)添加一个新元素(void SLList::pushBack(const Data &rDATA))时,我遇到了分段错误。由0xbaadf00d值引起的分段错误。 .................................................. .................................................. ....

IniFile.h

#include "Section.h"
class IniFile
{
  public:
    IniFile() :
    void addSection();

  private:
    SLList<Section> mContent;
};

IniFile.cpp

#include "IniFile.h"
IniFile::IniFile() :
   mContent() {}

void IniFile::addSection() // This is the only one method what i call
{
   mContent.pushBack(Section());
}

Section.h

#include "Pair.hxx"
#include "SLList.hxx"
class Section
{
  public:
    Section();

  private:
    SLList<Pair<std::string, std::string>> mKeyValuePairs;
};

Section.cpp

#include "Section.h"
Section::Section() :
    mKeyValuePairs() {}

SLList.hxx

template <typename Data>
class SLList
{
  public:
    class Node
    {
      public:
        Node(const Data &rDATA, Node *const pNEXT = nullptr) :
            mData(rDATA),
            mNext(pNEXT) {}

        Node(const Node &rRHS)
        {
            mData = rRHS.mData;
            *mNext = *rRHS.mNext;
        }

        ~Node()
        {
            delete mNext;
        }

        Node &operator=(const Node &rRHS)
        {
            if (&rRHS == this)
                return *this;
            mData = rRHS.mData;
            *mNext = *rRHS.mNext;
            return *this;
        }

      private:
        void setNext(Node *const pNext)
        {
            mNext = pNext;
        }

        friend void SLList<Data>::pushBack(const Data &rDATA);

      private:
        Data mData;
        Node *mNext;
    };

    SLList() :
        mHead(nullptr),
        mTail(nullptr) {}


    SLList(const SLList &rRHS)
    {
        *mHead = *rRHS.mHead;
        *mTail = *rRHS.mTail;
    }

    SLList &operator=(const SLList &rRHS)
    {
        if (&rRHS == this)
            return *this;
        *mHead = *rRHS.mHead;
        *mTail = *rRHS.mTail;
        return *this;
    }

    ~SLList()
    {
        clear();
    }

    void clear()
    {
        delete mHead;
    }

    void pushBack(const Data &rDATA)
    {
        Node *pNode = new Node(rDATA, nullptr); // I get segmentation fault at this point
        if (!mTail)
        {
            mHead = pNode;
            mTail = pNode;
        }
        else
        {
            mTail->setNext(pNode);
            mTail = pNode;
        }
    }

  private:
    Node *mHead;
    Node *mTail;
};

Pair.hxx

template <typename T1, typename T2>
class Pair
{
  public:
    Pair(const T1 &rFIRST, const T2 &rSECOND) :
        mFirst(rFIRST),
        mSecond(rSECOND) {}

  private:
    T1 mFirst;
    T2 mSecond;
};

1 个答案:

答案 0 :(得分:0)

{p> SLList的复制构造函数和赋值运算符在Node*指针管理方面是错误的。

此外,Node的析构函数不应销毁列表中的下一个Node对象。递归析构函数不仅对长列表不利,而且如果您想要在不清除整个列表的情况下删除单个Node,也会考虑将来。您的clear()方法应该直接迭代删除Node个对象的列表,而不使用递归。

尝试更像这样的事情:

#include <utility>
template <typename Data>
class SLList
{
public:
    class Node
    {
    public:
        Node(const Data &rDATA, Node *const pNEXT = nullptr)
            : mData(rDATA), mNext(pNEXT)
        {
        }

        Node(const Node &rSRC)
            : mData(rSRC.mData), mNext(nullptr)
        {
        }

        Node &operator=(const Node &rRHS)
        {
            if (&rRHS != this)
                mData = rRHS.mData;
            return *this;
        }

    private:
        Data mData;
        Node *mNext;

        friend class SLList<Data>;
    };

    SLList()
        : mHead(nullptr), mTail(nullptr)
    {
    }

    SLList(const SLList &rSRC)
        : mHead(nullptr), mTail(nullptr)
    {
        Node *pNode = rSRC.mHead;
        while (pNode)
        {
            pushBack(pNode->mData);
            pNode = pNode->mNext;
        } 
    }

    SLList &operator=(const SLList &rRHS)
    {
        if (&rRHS != this)
        {
            SLList temp(rRHS);
            std::swap(mHead, temp.mHead);
            std::swap(mTail, temp.mTail);
        }
        return *this;
    }

    ~SLList()
    {
        clear();
    }

    void clear()
    {
        Node *pNode = mHead;
        mHead = mTail = nullptr;
        while (pNode)
        {
            Node *pNext = pNode->mNext;
            delete pNode;
            pNode = pNext;
        }
    }

    void pushBack(const Data &rDATA)
    {
        Node *pNode = new Node(rDATA);
        if (!mHead) mHead = pNode;
        if (mTail) mTail->mNext = pNode;
        mTail = pNode;
    }

private:
    Node *mHead;
    Node *mTail;
};

话虽如此,真正应该做的是使用std::list(或std::forward_list)和std::pair代替。根本没有“重新发明轮子”的好处:

#include "Section.h"
#include <list>
class IniFile
{
public:
    void addSection();
private:
    std::list<Section> mContent;
};

#include "IniFile.h"
void IniFile::addSection()
{
    mContent.push_back(Section());
}

#include <pair>
#include <list>
#include <string>
class Section
{
private:
    std::list<std::pair<std::string, std::string>> mKeyValuePairs;
};

#include <list>
template <typename Data>
class SLList
{
public:
    void clear()
    {
        mList.clear();
    }

    void pushBack(const Data &rDATA)
    {
        mList.push_back(rDATA);
    }

private:
    std::list<Data> mList;
};