Эксперт .NET
 Аватар для Даценд
5878 / 4755 / 2939
Регистрация: 20.04.2015
Сообщений: 8,361

"Нарушение прав доступа при чтении по адресу" при чтении структур из бинарного файла

13.12.2017, 22:48. Показов 4788. Ответов 8
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Пытаюсь разобраться со структурами в бинарных файлах.
Допустим, есть массив структур. Записываю его в бинарный файл (закомментированный код). Всё прекрасно записывается.
Затем читаю и добавляю структуры в вектор. Всё прекрасно читается, добавляется и даже выводится на экран.
Но при выполнении строки return 0; получаю ошибку "Нарушение прав доступа при чтении по адресу".
Код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
using namespace std;
 
struct student
{
    int id;
    string name;
    int age;
};
 
int main()
{
        //student group[3];
    //group[0].id = 1; group[0].name = "Ivanov I.I.";  group[0].age = 25;
    //group[1].id = 2; group[1].name = "Petrov P.P.";  group[1].age = 35;
    //group[2].id = 3; group[2].name = "Sidorov S.S.";  group[2].age = 20;
    //ofstream out_file("e://file.dat", ios::binary | ios::out);
    //for (int i = 0; i < 3; i++)
    //{
    //  out_file.write((char*)(group+i), sizeof(student));
    //}
    //out_file.close();
 
    vector<student> group;
    student tmp;
    ifstream in_file("e://file.dat", ios::binary | ios::in);
    while (in_file.read((char*)(&tmp), sizeof(student))) //читаем
        group.push_back(tmp); //добавляем
    in_file.close();
    for (auto stud : group)
        cout << stud.id << "\t" << stud.name << "\t" << stud.age << endl; //выводим
    return 0; //а здесь нарушение прав доступа при чтении по адресу...
}
Если выделить память под tmp динамически, а после чтения присвоить nullptr, то ошибки нет:
C++
1
2
3
4
5
6
7
8
9
10
vector<student> group;
student *tmp = new student;
ifstream in_file("e://file.dat", ios::binary | ios::in);
while (in_file.read((char*)(tmp), sizeof(student))) 
    group.push_back(*tmp);
tmp = nullptr;
in_file.close();
for (auto stud : group)
    cout << stud.id << "\t" << stud.name << "\t" << stud.age << endl;
delete tmp;
Собственно вопросы: почему всё так происходит и как сделать правильно?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
13.12.2017, 22:48
Ответы с готовыми решениями:

нарушение прав доступа при чтении по адресу
Здравстуйте. Хочу передать кучу параметров в функцию Font font; POINT screen; VertexArray liness(Lines, 84); Text...

Нарушение прав доступа при чтении по адресу
Помохите! При работе со строками выдает вот такую ошибку. При проверке с английским алфавитом все работало. П.5.18.Правил Запрещено...

Нарушение прав доступа при чтении по адресу
Доброго времени суток форумчане, не понимаю откуда берется ошибка #define _CRT_SECURE_NO_WARNINGS #include &lt;iostream&gt; ...

8
277 / 226 / 93
Регистрация: 27.06.2016
Сообщений: 639
13.12.2017, 23:11
Даценд, вы записываете и читаете бинарные данные "как есть". Учитывая, что std::string содержит в себе указатель на данные в динамической памяти (разве что малые строки могут быть размещены внутри самого объекта), вы считываете из файла висячий указатель, а не саму строку.
1
1718 / 567 / 187
Регистрация: 12.03.2016
Сообщений: 2,169
13.12.2017, 23:28
Запись класса в bin файл
1
Эксперт .NET
 Аватар для Даценд
5878 / 4755 / 2939
Регистрация: 20.04.2015
Сообщений: 8,361
14.12.2017, 00:57  [ТС]
Попробовал читать/писать поля раздельно.
Вот что получилось:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
using namespace std;
 
struct student
{
    public:
        int id;
        string name;
        int age;
 
        void write(ofstream &file)
        {
            file.write((char*)&id, sizeof(id));
            nameLength = name.size();
            file.write((char*)&nameLength, sizeof(nameLength));
            file.write(name.c_str(), nameLength);
            file.write((char*)&age, sizeof(age));
        }
 
        bool read(ifstream &file)
        {
            if(!file.read((char*)&id, sizeof(id))) return false;
            file.read((char*)&nameLength, sizeof(nameLength));
            char* cname = new char[nameLength];
            file.read(cname, nameLength);
            name = string(cname, nameLength);
            file.read((char*)&age, sizeof(age));
            return true;
        }
    private:
        size_t nameLength;
};
 
int main()
 
{
    student group[3];
    group[0].id = 1; group[0].name = "qwertyuiopqwertyuiop a.d.";  group[0].age = 25;
    group[1].id = 2; group[1].name = "adfvjanfdpvajdfpvadjfnvodf g.g.";  group[1].age = 35;
    group[2].id = 3; group[2].name = "aouhdfbvosdfhvbaodfhvbdfovhsdbfvodhfvb h.h.";  group[2].age = 20;
    ofstream out_file("e://file.dat", ios::binary | ios::out);
    for (int i = 0; i < 3; i++)
    {
        group[i].write(out_file);
    }
    out_file.close();
 
    vector<student> groupvec;
    student tmp;
    ifstream in_file("e://file.dat", ios::binary | ios::in);
    while (tmp.read(in_file)) 
        groupvec.push_back(tmp);
    in_file.close();
    for (auto stud : groupvec)
        cout << stud.id << "\t" << stud.name << "\t" << stud.age << endl;
    return 0;
}
Если это страшный г-код, то так и скажите. Только объясните, почему
Особо интересно мнение о методах в структуре, и использовании private-поля для хранения длины поля name.
0
 Аватар для Kuzia domovenok
4266 / 3325 / 925
Регистрация: 25.03.2012
Сообщений: 12,528
Записей в блоге: 1
14.12.2017, 01:18
size_t nameLength; нужно бы сделать локальной переменной, а не полем класса
Ещё char* cname = new char[nameLength]; в конце этой же функции освободить delete cname

а так вроде норм
1
Эксперт .NET
 Аватар для Даценд
5878 / 4755 / 2939
Регистрация: 20.04.2015
Сообщений: 8,361
14.12.2017, 01:28  [ТС]
Kuzia domovenok,
Благодарю.
Вечно забываю память освобождать и с локальным nameLength совершенно согласен.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void write(ofstream &file)
{
    file.write((char*)&id, sizeof(id));
    size_t nameLength = name.size();
    file.write((char*)&nameLength, sizeof(nameLength));
    file.write(name.c_str(), nameLength);
    file.write((char*)&age, sizeof(age));
}
 
bool read(ifstream &file)
{
    if(!file.read((char*)&id, sizeof(id))) return false; //вот эта проверка
    size_t nameLength;
    file.read((char*)&nameLength, sizeof(nameLength));
    char* cname = new char[nameLength];
    file.read(cname, nameLength);
    name = string(cname, nameLength);
    file.read((char*)&age, sizeof(age));
    delete[] cname;
    return true;
}
А ссылку на поток в функцию передавать это нормально?
И проверка чтения корректна?
0
 Аватар для QuakerRUS
1468 / 1009 / 456
Регистрация: 30.10.2017
Сообщений: 2,799
14.12.2017, 02:26
Цитата Сообщение от Даценд Посмотреть сообщение
А ссылку на поток в функцию передавать это нормально?
Да.

Цитата Сообщение от Даценд Посмотреть сообщение
И проверка чтения корректна?
В данном случае проверяется только корректность чтения первого значения. Думаю правильнее будет считать все значения и после этого проверить поток на ошибки. Перед созданием динамического массива проверка думаю тоже не помешает.

Добавлено через 5 минут
Так же, если б у вас текстовые поля имели фиксированный размер, можно было бы сделать например так.

C++
1
2
3
4
5
// ...
file.write((char *)&MyStruct, sizeof(MyStruct));
// ...
file.read((char *)&MyStruct, sizeof(MyStruct));
// ...
1
Эксперт .NET
 Аватар для Даценд
5878 / 4755 / 2939
Регистрация: 20.04.2015
Сообщений: 8,361
14.12.2017, 10:45  [ТС]
Цитата Сообщение от QuakerRUS Посмотреть сообщение
В данном случае проверяется только корректность чтения первого значения.
Это задумывалось как проверка на то, есть ли еще что читать в потоке.
Пробовал проверять через eof, выбрасывает исключение:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
bool read(ifstream &file)
{
    if(file.eof()) return false;
    file.read((char*)&id, sizeof(id));
    size_t nameLength;
    file.read((char*)&nameLength, sizeof(nameLength));
    char* cname = new char[nameLength];
    file.read(cname, nameLength);
    name = string(cname, nameLength);
    file.read((char*)&age, sizeof(age));
    delete[] cname;
    return true;
}
0
 Аватар для QuakerRUS
1468 / 1009 / 456
Регистрация: 30.10.2017
Сообщений: 2,799
14.12.2017, 11:52
Даценд, а если у вас неожиданно файл оборвется после чтения id, или в этот момент произойдет отказ диска? В программу попадут некорректные данные, что может вызвать ошибку. То, что вы и наблюдаете, когда делаете проверку на eof перед чтением первого блока. eof устанавливается после попытки считать несуществующий элемент, а не когда указатель находится в конце файла. eof-проверку вы успешно проходите перед чтением несуществующего элемента, и далее программа ведет себя некорректно, пытаясь обработать данные, полученные из нерабочего потока.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
14.12.2017, 11:52
Помогаю со студенческими работами здесь

Нарушение прав доступа при чтении по адресу
Здравствуйте, форумчане. Дабы не писать долго я описал свою проблему в видео https://youtu.be/oufPPGrGiek

Нарушение прав доступа при чтении по адресу
Доброго времени суток. Делал задание из Лафоре, и заметил, что при попытке прочитать данные из файла выдаёт ошибку (скрин). Мои действия с...

Нарушение прав доступа при чтении по адресу
Есть функция, которая сортирует структуру AEROFLOT по методу Шелла. Там я считаю количество сравнений и перестановок. При вызове функции...

Нарушение прав доступа при чтении по адресу
В приведённом ниже коде возникает ошибка времени выполнения с текстом из названия. Проблема в том, что остановка выполнения происходит...

Нарушение прав доступа при чтении по адресу
#include &lt;iostream&gt; #include &lt;locale.h&gt; #include &lt;cstring&gt; #include &lt;cmath&gt; using namespace std; class String { ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Опции темы

Новые блоги и статьи
Blazor и контроллер сервопривода IoT Meadow Maple
Wired 11.07.2025
Я решил разобраться, как можно соединить современные веб-технологии с миром "железа". Интересная комбинация получилась из Blazor в качестве веб-интерфейса и микроконтроллера Meadow с его веб-сервером. . .
Генерация OpenQASM из кода Q#
EggHead 10.07.2025
Летом 2024-го я начал эксперименты с библиотекой Q# Bridge, и знаете что? Она оказалась просто находкой для тех, кто работает на стыке разных квантовых экосистем. Основная фишка этой библиотеки -. . .
Изучаем новый шаблон ИИ-чата .NET AI Chat Web App
stackOverflow 10.07.2025
В . NET появилось интересное обновление - новый шаблон ИИ-чата под названием . NET AI Chat Web App. Когда я впервые наткнулся на анонс этого шаблона, то сразу понял, что Microsoft наконец-то. . .
Результаты исследования от команды ARP (июль 2025 г.)
Programma_Boinc 10.07.2025
Результаты исследования от команды ARP (июль 2025 г. ) Африканский проект по дождям (ARP) World Community Grid снова запущен! Мы рады поделиться обновленной информацией о нашем прогрессе с осени. . .
Angular vs Svelte - что лучше?
Reangularity 09.07.2025
Сегодня рынок разделился на несколько четких категорий: тяжеловесы корпоративного уровня (Angular), гибкие универсалы (React), прогрессивные решения (Vue) и новая волна компилируемых фреймворков. . .
Code First и Database First в Entity Framework
UnmanagedCoder 09.07.2025
Entity Framework дает нам свободу выбора, предлагая как Code First, так и Database First подходы. Но эта свобода порождает вечный вопрос — какой подход выбрать? Entity Framework — это. . .
Как использовать Bluetooth-модуль HC-05 с Arduino
Wired 08.07.2025
Bluetooth - это технология, созданная чтобы заменить кабельные соединения. Обычно ее используют для связи небольших устройств: мобильных телефонов, ноутбуков, наушников и т. д. Работает она на частоте. . .
Руководство по структурам данных Python
AI_Generated 08.07.2025
Я отчетливо помню свои первые серьезные проекты на Python - я писал код, он работал, заказчики были относительно довольны. Но однажды мой наставник, взглянув на мою реализацию поиска по огромному. . .
Тестирование энергоэффективности и скорости вычислений видеокарт в BOINC проектах
Programma_Boinc 08.07.2025
Тестирование энергоэффективности и скорости вычислений видеокарт в BOINC проектах Опубликовано: 07. 07. 2025 Рубрика: Uncategorized Автор: AlexA Статья размещается на сайте с разрешения. . .
Раскрываем внутренние механики Android с помощью контекста и манифеста
mobDevWorks 07.07.2025
Каждый Android-разработчик сталкивается с Context и манифестом буквально в первый день работы. Но много ли мы задумываемся о том, что скрывается за этими обыденными элементами? Я, честно говоря,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru