单向链表 - 分段错误

Singly linked list - Segmentation fault

首先,对于长代码感到抱歉。我尽力 trim 它越小越好。 当我想将新元素 (void SLList::pushBack(const Data &rDATA)) 添加到我的单向链表(在 SLList.hxx 中)时出现分段错误。由 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;
};

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。 "reinventing the wheel" 一点好处都没有:

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