сохранять и извлекать связанный список через файлы, используя переполнение стека

Я создал программу для хранения и получения связанного списка с использованием 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 *)&current, sizeof(link));
current->another = NULL;
head = current;
}
preceding = current;
datafile.read((char *)&current->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

Решение

Мой любимый совет для начинающих: начинайте с малого и просто, сделайте так, чтобы он работал идеально, а затем добавляйте немного сложности, тестируя на каждом шагу. У вас есть три независимые функции: базовый список, присвоение случайных значений списку и чтение / запись списка. Вы должны были разработать их самостоятельно, а затем объединить их; тот факт, что вы не знаете, какая часть вызывает проблему, показывает, что вы пытались написать их все сразу. (Хорошо, факт, что их соответствующие коды запутаны, показывает это также.)

Самая большая проблема в коде чтения файла (который находится в конструктор по умолчанию всех мест). Вы помещаете данные в неинициализированную память:

link *current;
...
current = NULL;
...
datafile.read((char *)&current, sizeof(link));

Это все равно, что наливать горячий кофе без поиска чашки. Вы должны работать на чтение / запись — и научиться не делать этого — с такими простыми типами, как char а также int прежде чем попробовать это со сложными типами. Затем попробуйте читать / писать с одним link, Затем с кучей их.

1

Другие решения

Ты получаешь 0xC0000005 ошибка из-за Нелегальный доступ к памяти так как вы делаете операции с указателями в вашей программе. Поскольку вы не предоставляете полные коды, вы можете выполнять недопустимые операции, например, не инициализировать указатель в другой части вашей программы.

0

Как уже было указано в бета-версии, нарушение прав доступа происходит при попытке прочитать ссылку:

     ...
datafile.read((char *)&current, sizeof(link));
...

«текущий» является указателем, и с помощью «&«Оператор на нем дает указатель на память, занятую самой переменной (где-то в стеке). Таким образом, код пытается прочитать какой-то кусок мусора данных размером с ссылку в этот указатель — но это не вызывает доступа Нарушение возникает, когда «current» разыменовывается и используется для записи в член объекта «link», на который он указывает:

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;
0
По вопросам рекламы [email protected]