我已经创建了一个使用c ++存储和检索链表的程序,但不幸的是我的程序没有正确检索数据并返回代码0xC0000005。我的计划有什么问题?我是初学者。
//C++ code
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cstring>
#include <ctime>
using namespace std;
struct link
{
link(int dat, link *nxt): data(dat), another(nxt)
{
}
int data;
link *another;
};
struct list
{
link *first;
~list();
list();
void addnew();
void displl();
}list;
list::list()
{
fstream datafile;
datafile.open("datafile", ios::in | ios::app);
datafile.seekg(0, ios::end);
int eb = datafile.tellg();
if(!eb)
{
first = NULL;
return;
}
datafile.seekg(0, ios::beg);
link *head, *current, *preceding;
head = preceding = current = NULL;
while(eb)
{
if(!current)
{
datafile.read((char *)¤t, sizeof(link));
current->another = NULL;
head = current;
}
preceding = current;
datafile.read((char *)¤t->another, sizeof(link));
current = current->another;
current->another = NULL;
preceding->another = current;
eb--;
}
first = head;
}
void list::addnew()
{
srand(time(0) + rand());
first = new link(rand()%10, first);
}
void list::displl()
{
link *current;
cout << endl << " - ";
for(current = first; current; current = current->another)
cout << current->data << " - ";
cout << endl;
}
list::~list()
{
fstream datafile;
datafile.open("datafile", ios::out | ios::app);
link *temp;
while(first != NULL)
{
temp = first;
first = first->another;
datafile.write((char *)&temp, sizeof(link));
delete temp;
}
first = NULL;
}
int main()
{
list.addnew();
list.addnew();
list.addnew();
list.displl();
system("pause");
return 0;
}
答案 0 :(得分:0)
由于非法内存访问而导致0xC0000005
错误,因为您正在程序中执行指针操作。因为您没有提供完整的代码,所以您可能正在进行非法操作,例如不在程序的其他部分初始化指针。
答案 1 :(得分:0)
正如Beta已经指出的那样,尝试阅读链接时会发生访问冲突:
...
datafile.read((char *)¤t, sizeof(link));
...
“current”是一个指针,使用“&amp;” operator on it给出了一个指针,指向变量本身占用的内存(在堆栈的某个地方)。因此,代码尝试将一些链接大小的垃圾数据块读入此指针 - 但这不会导致访问冲突。当“current”被取消引用并用于写入它指向的“链接”对象的成员时,会发生异常:
current->another = NULL;
从数据文件加载的值来自类似错误的序列化代码 - 没有保存“链接”数据。所有文件都包含来自堆上分配的“链接”对象的旧内存地址 - 这些地址无效,因为它们的内存是在以前的程序会话中分配的。
成功序列化对象的字节图像如下所示:
datafile.write(reinterpret_cast<const char*>(temp), sizeof(*temp));
但是“链接”对象不是普通的旧数据 - 在您销毁此链接对象后,它包含的指针将无效。因此,加载列表必须包括为每个链接分配内存(如“addnew”)。
您可能只想从头开始走列表,并保存每个链接的有效负载数据,如下所示:
datafile.write(reinterpret_cast<const char*>(&temp->data), sizeof(temp->data));
然后,要加载列表,请为每个节点将有效负载读入临时变量:
datafile.read(reinterpret_cast<char*>(&temp_data), sizeof(temp_data));
如果此操作成功,请分配并构造堆“link”对象并将其连接到上一个节点:
next_tail = new link(temp_data, 0);
tail->another = next_tail;
tail = next_tail;