std::length_error at memory location

I have a problem which I just can't figure it out. It happens in case 2 "Check info about a student". When the program is launched and first a group of students is created and then check info is selected everything is fine. The information is shown. But if I exit the program and then launch it again. When trying straight up checking info it throws the error.
Line 153: std::length_error at memory location

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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
  #include <iostream>
#include <string>
#include <cstring>
#include <stdlib.h>
#include <conio.h>
#include <fstream>

const int N=30; //max students
const char students[]="students.dat";
struct student
{
	std::string fnom;
	std::string name;
	char sex;
	int age;
	int ocenki[4];
	double srusp;
};
int n;
std::fstream fp;
void menu();
void crstudent(struct student stud[]);
void chkinfo(struct student stud[]);
void addstudent();
void back();
int main()
{
    menu();
}
void menu()
{
    struct student stud[N];
    int choice;
    do
    {
        do
		{
			std::cout << "---------------//MENU//---------------\n\n";
			std::cout << "Choose one of the following options: \n\n";
            std::cout<<"1.Add a new student.\n"
                     <<"2.Check info about a student.\n"
                     <<"3..\n"
                     <<"4..\n"
                     <<"5.Exit program.\n\n";
			std::cout << "Input: ";
            std::cin>>choice;
            system("CLS");
        }
        while(choice<1||choice>5);
        switch(choice)
        {
        case 1:
        {
            int ch1;
            do
            {
                std::cout<<"1. Create a group of students.\n"
                         <<"2. Add a new student.\n"
                         <<"3. Back.\n";
                std::cin>>ch1;
                system("CLS");
            }
            while(ch1<1||ch1>3);
            switch(ch1)
            {
            case 1:
                crstudent(stud);
                break;
            case 2:
                addstudent();
                break;
            case 3:
                continue;
                break;
            }
            break;
        }

        case 2:
            chkinfo(stud);
            break;
        case 3:
            break;
        case 4:
            break;
        case 5:
            exit(0);
            break;
        default:
            std::cout<<"Wrong input.\n"<<"Try again.\n";
        }
    }
    while (choice !=5);
}
void crstudent(struct student stud[])
{
    fp.open("students.dat",std::ios::out|std::ios::binary);
    if(!fp)
    {
        std::cout<<std::endl<<"Error creating the file!";
        exit(1);
    }
    std::cout<<"Input the number of students you wish to add: ";
    std::cin>>n;
    for(int i=0; i<n; i++)
    {
        fflush(stdin);
        std::cout<<"Input student "<<i+1<<" faculty number: ";
		std::cin.ignore();
        std::getline(std::cin,stud[i].fnom);
        std::cout<<"Input student's name: ";
        std::getline(std::cin,stud[i].name);
		fp << stud[i].name;
        std::cout<<"Input student's age: ";
        std::cin>>stud[i].age;
        std::cout<<"Input student's sex - M or F: ";
		std::cin >> stud[i].sex;
		stud[i].sex=std::toupper(stud[i].sex);//Converting lowercase to uppercase
        stud[i].srusp=0;
        std::cout<<"Input student's marks: \n";
        for(int k=0; k<4; k++)
        {
            std::cout<<"Input mark number "<<k+1<<": ";
            std::cin>>stud[i].ocenki[k];
            stud[i].srusp+=stud[i].ocenki[k];
        }
        stud[i].srusp=stud[i].srusp/4.00;
        std::cout<<std::endl;
    }
    fp.write((char*)stud,n* static_cast<int64_t>(sizeof(student)));
    fp.close();
    system("CLS");
}
void chkinfo(struct student stud[])
{
	std::streamoff pos;
	student s;
	fp.open("students.dat", std::ios::in | std::ios::binary);
	if (!fp)
	{
		std::cout << std::endl << "File does not exist!";
		exit(1);
	}
	fp.seekg(0L, std::ios::end);
	pos = fp.tellg();//conversion from 'std::streamoff' to 'long', possible loss of data
	fp.close();
	fp.open("students.dat", std::ios::in | std::ios::binary);
	fp.seekg(0);
	for (unsigned int i = 0; i < (pos / sizeof(student)); i++)
	{
		fp.read((char*)&s, sizeof(student));
		stud[i] = s;
		std::cout << std::endl << "Faculty number: " << stud[i].fnom;
		std::cout << std::endl << "Name: " << stud[i].name;
		std::cout << std::endl << "Age: " << stud[i].age;
		std::cout << std::endl << "Sex: " << stud[i].sex;
		std::cout << std::endl << "Average result is: " << stud[i].srusp;
		std::cout << std::endl;
	}
	fp.close();
	back();
Last edited on
You can't fp.write() and fp.read() std::string objects in your student structure.

Each std::string has an internal pointer to somewhere else in memory where your actual string is stored.

Which is fine so long as you don't quit the program, or cause your array to go out of scope.

But as soon as you do, that string data is gone for good.
Just load your students.dat file into a hex editor, you will not see your strings.

So when you quit and reload, you're SoL, because the memory and the strings are gone.

Edit:
> fflush(stdin);
No - absolutely not.
If you're doing your cin.ignores properly, you don't need this abortion.
Last edited on
I understand! It makes sense actually. So what are my alternative options? Can you recommend me something?
Well the crude way out is to just use char arrays.

Proper robust serialisation of data structures is a minefield and a PITA in C++.
Thank you! It is now working.
Topic archived. No new replies allowed.