我正在创建一个双链表,我得到一个奇怪的错误,花了好几个小时来调试但是没有这样做,尝试了一个在线调试器,甚至没有帮助
程序确实编译并运行,但崩溃了我得到的错误
双链接list.exe中0x770215ee处的未处理异常:0xC0000005:访问冲突写入位置0x00000004。
在线调试程序结果http://onlinegdb.com/Bkta6O6ig
在线调试器提供了三个错误,我在下面的代码中提到了注释
我的猜测是类列表的添加功能有问题
班级节点
#include <iostream>
using namespace std;
class node
{
private:
int data;
node *prev_pointer;
node *next_pointer;
public:
int get_data()
{
return data;
}
void set_data(int data)
{
this->data = data;
}
node* get_prev_ptr()
{
return prev_pointer;
}
void set_next_ptr(node *Node)
{
next_pointer = Node;
}
node* get_next_ptr()
{
return next_pointer;
}
void set_prev_ptr(node *hi)
{
prev_pointer = hi; //First error
}
};
班级列表
class List
{
private:
int size;
node * cursor;
node * lastnode;
node * headnode;
public:
List();
void add(int data);
bool next();
void previous();
void start();
void traverse();
int get_data();
// ~List();
};
List :: List()
{
headnode = new node();
cursor = NULL;
lastnode = NULL;
size = 0;
}
void List:: add(int data)
{
node *newnode = new node();
newnode->set_data(data);
if ( cursor != NULL )
{
newnode->set_next_ptr(cursor->get_next_ptr());
newnode->set_prev_ptr(cursor);
(newnode->get_next_ptr())->set_prev_ptr(newnode); //2nd error
cursor->set_next_ptr(newnode);
lastnode = cursor;
cursor = cursor->get_next_ptr();
}
else
{
newnode->set_next_ptr(NULL);
newnode->set_prev_ptr(headnode);
headnode->set_next_ptr(newnode);
cursor = newnode;
lastnode = headnode;
}
size++;
}
bool List :: next()
{
if ( cursor != NULL )
{
return false;
}
else
{
lastnode = cursor;
cursor = cursor->get_next_ptr();
}
if( cursor == NULL || size == 0 )
return false;
else
return true;
}
void List :: traverse()
{
node *temp = cursor;
start();
for ( int i = 0 ; next() ; i++ )
{
cout<<"element " << i << " " << cursor->get_data() <<endl;
}
}
void List :: start()
{
lastnode = headnode;
cursor = headnode;
}
int List :: get_data()
{
return cursor->get_data();
}
主要
int main()
{
List list;
list.add(10);
list.add(11); //3rd error
list.add(12);
//list.add(13);
//list.add(14);
//list.add(15);
list.traverse();
return 0;
}
答案 0 :(得分:3)
预付:阅读debuger输出:
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400d20 in node::set_prev_ptr (this=0x0, hi=0x614c60) at main.cpp:46
46 prev_pointer = hi;
注意this=0x0
。所有类方法都有一个this指针,以便它们知道要操作的许多可能实例中的哪一个。这里this
指向NULL。程序无法从NULL对象获取有效的prev_pointer
。这告诉您,要找到问题的真正原因,您需要找出this
无效的原因。
这就是callstack进来的地方。你向后移动堆栈以找出this
被摧毁的地方。我们可以看到在set_prev_ptr
和get_next_ptr
的输出上调用get_next_ptr
uis会返回next_pointer
。首先要看的是next_pointer
。将newnode->next_pointer
放入&#34;显示表达式&#34;表明next_pointer
为NULL。
为什么next_pointer
为空呢?我们找到几行代码
newnode->set_next_ptr(cursor->get_next_ptr())
所以我们查看cursor->next_pointer
并发现它是NULL。现在我们进入原始帖子并绘制链接列表,因为它比一遍又一遍地运行和重新运行调试器要快得多。
调试链表的最佳方法是使用铅笔和纸张:绘制它。添加10后,您会看到列表看起来像
head <-> 10 -> NULL
cursor -> 10 -> NULL
lastnode -> 10 -> NULL
添加11应该看起来像
head <-> 10 <-> 11 -> NULL
cursor -> 11 -> NULL
lastnode -> 10 -> 11 -> NULL
不幸的是它失败了,因为
(newnode->get_next_ptr())->set_prev_ptr(newnode);
尝试
11 -> NULL -> 11;
所以
if (newnode->get_next_ptr() != NULL)
需要保护它。
此外,重新思考
lastnode = cursor;
自从cursor
以来明确newnode
cursor
的下一个点不是最后一个节点。根据{{1}}点的位置,cursor
可能不是最后一个节点。
建议:
提供那些开放的next和prev访问器会导致newnode
的封装失败,因为任何人都可以使用访问器执行他们想要的任何操作node
。您也可以声明成员变量node
并节省时间。
这似乎是public
成为List
friend
或节点全部{{1}}访问权限(或node
)的好例子并且远离窥探眼睛封装在public
内。无论哪种方式,都会失去访问者。