【问题标题】:0xC0000005: Access violation writing location 0x00000004.'0xC0000005:访问冲突写入位置 0x00000004。
【发布时间】:2014-02-11 02:37:13
【问题描述】:

我创建了这个链表类以在我的工作中使用它,但我有这个异常“game.exe 中 0x003216D2 的第一次机会异常:0xC0000005:访问冲突写入位置 0x00000004。”它来自擦除功能,有人可以告诉我如何修复它并解释它的问题

#ifndef LINKEDLIST_HPP
#define LINKEDLIST_HPP


#include <vector>
#include <cassert>

template<typename T>
class Linkedlist
{
private:    
    // The basic doubly linked Linkedlist node.
    // Nested inside of Linkedlist, can be public
    // because the Node is itself private
    struct Node
    {
        T  _data;
        Node   *_prev;
        Node   *_next;

        Node( const T & d = T(), Node * p = NULL, Node * n = NULL )
            : _data( d ), _prev( p ), _next( n ) { }


        // Rvalue   
        Node(Node && n)
        {
            _data = std::move(n._data);
            _prev = std::move(n._prev);
            _next = std::move(n._next);
        }

        // = operator
        Node& operator =(Node && n)
        {
            _data = std::move(n._data);
            _prev = std::move(n._prev);
            _next = std::move(n._next);
            return *this;
        }
    };
public:
    class LinkedListIter : public std::iterator<std::forward_iterator_tag , T , int>
    {
        Node* _node;
    public:
        LinkedListIter(Node* p=nullptr) : _node(p){}
        ~LinkedListIter(){}

        Node* getNode(){return _node;}

        T operator * () { return _node->_data; }
        LinkedListIter & operator ++()
        {
            _node = _node->_next;
            return *this; 
        }

        LinkedListIter operator ++(int)
        {
            LinkedListIter  retVal = *this;
            ++this;
            return retVal;
        }
        bool operator < (LinkedListIter const& rhs) const
        { 
            return _Node < rhs._Node; 
        }
        bool operator != (LinkedListIter const& rhs) const
        {
            return _Node != rhs._pNode;
        }
        bool operator == (LinkedListIter const& rhs) const 
        {
            return _Node == rhs._Node;
        }
    };



    Linkedlist( )
    { init(); }

    ~Linkedlist()
    {
        clear();
        delete _head;
        delete _tail;
    }

    Linkedlist(const Linkedlist & rhs)
    {
        init( );
        *this = rhs;
    }

    const Linkedlist & operator= (const Linkedlist & rhs)
    {
        if( this == &rhs )
            return *this;
        clear( );
        for(const_iterator itr = rhs.begin(); itr != rhs.end( ); ++itr)
            push_back(*itr);
        return *this;
    }

    // Return iterator representing beginning of Linkedlist.
    // Mutator version is first, then accessor version.
    LinkedListIter begin()
    { return LinkedListIter(_head->_next);}


    // Return iterator representing endmarker of Linkedlist.
    // Mutator version is first, then accessor version.
    LinkedListIter end()
    { return LinkedListIter(_tail); }


    // Return number of elements currently in the Linkedlist.
    int size() const
    { return _size; }

    // Return true if the Linkedlist is empty, false otherwise.
    bool empty() const
    { return size() == 0; }

    void clear()
    {
        while( !empty() )
            pop_front();
    }

    // front, back, push_front, push_back, pop_front, and pop_back
    // are the basic double-ended queue operations.
    T & front()
    //{ return *begin( ); }
    {return _head->_next.data}
    const T & front() const
    { return *begin(); }

    T & back( )
    { return *--end(); }

    const T & back() const
    { return *--end(); }

    void push_front(const T & x)
    { insert( begin(), x ); }

    void push_back(const T & x)
    { insert( end(), x ); }

    void pop_front()
    { erase(begin()); }

    void pop_back()
    { erase(--end()); }

    // Insert x before itr.
    LinkedListIter insert(LinkedListIter& itr, const T & x)
    {
        Node *p = new Node(x,itr.getNode()->_prev,itr.getNode());
        _size++;
        return LinkedListIter(p->_prev = p->_prev->_next = new Node(x, p->_prev, p));
    }

    // Erase item at itr.
    LinkedListIter  erase(LinkedListIter itr)
    {
        Node *p = itr.getNode();
        LinkedListIter retVal(p->_next);
        p->_prev->_next = p->_next;
        p->_next->_prev = p->_prev;
        delete p;
        _size--;

        return retVal;


    }

    LinkedListIter erase(LinkedListIter start, LinkedListIter end)
    {
        for(iterator itr = start; itr != end;)
            itr = erase(itr);

        return end;
    }

private:
    int   _size;
    Node *_head;
    Node *_tail;




    void init()
    {
        _size = 0;
        _head = new Node;
        _tail = new Node;
        _head->_next = _tail;
        _tail->_prev = _head;
    }
};

#endif

【问题讨论】:

  • 除非您正在做需要编写自己的类的作业,否则请使用 std::list。有用!为什么要使用右值引用(&&)?我猜你正在学习 C++,我猜你没有得到右值的细微差别。提示:如果你打得好,编译器会为你编写那些默认的右值函数。
  • 您是否使用调试器查看错误在哪一行?
  • 编写单元测试来验证它是否按预期工作。对于非常简单的事情,从完全简单的情况开始,例如,size() 在第一次构造时返回零,size() 在推送一个项目后返回一个,在推送一个项目后,front() 正确返回该项目,等等。在一个做一些事情的小测试用例中调查一个问题要比在将它用于实际任务时挖掘一些大的复杂崩溃要容易得多。随着越来越多的测试通过,添加越来越残酷的新测试。
  • @jeffamaphone 异常发生在行擦除函数行 p->_next->_prev = p->_prev;
  • @user3277743:所以在p-&gt;_next-&gt;_prev 中,子表达式p-&gt;_next 为空。你有一个很好的提示,一个节点的_next 指针为空。现在检查该节点是如何创建和插入的,以及 null 是否是该指针的有效值。

标签: c++ visual-c++ c++11 data-structures


【解决方案1】:

访问冲突(在 windows 中,或在 unices 中出现分段错误)表明您尝试错误地访问内存。您尝试访问进程空间之外的内存,或者您尝试了错误的访问类型。

错误消息还告诉您您尝试访问的地址是什么以及您尝试的访问类型。您尝试写入内存地址 0x00000004,即距离第零地址 4 个字节。看起来您试图通过空指针进行写入,并且写入的是距离对象开头 4 个字节的成员。

虽然并不总是能够确定真正的原因是什么,但这就是它看起来的样子。调试问题的最简单方法是在调试器中运行您的应用程序,并让调试器告诉您访问冲突在哪里。然后检查程序的状态并尝试确定它是如何在那种情况下结束的。

【讨论】:

  • 问题我无法调试 p->_prev->_next = p->_next 的值;因为是我们的指针,我试图添加观察者来查看我无法查看的值跨度>
  • @user3277743:让它在调试器中崩溃,它会告诉你哪个指针是空的。然后试着弄清楚它是怎么来的。如果这没有帮助,那么尝试将代码减少到最小的崩溃部分并进入程序。什么功能崩溃了?列表之前是如何初始化的?你能在它崩溃之前检查出什么问题吗?
【解决方案2】:

你应该检查你的指针。尝试仔细调试erase 函数。

Access violation 错误通常发生在您的指针指向“外部”内存区域(即应用程序未保留的内存)时。

【讨论】:

    【解决方案3】:

    您可能试图删除尾节点。尾节点的next 指针为NULL(来自默认构造函数)。

    【讨论】:

      猜你喜欢
      • 2014-05-07
      • 2012-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多