Firstly, Here's my code running in VS 2010

#include <iostream>
#include <fstream>
#include <string>
#include <list>
using namespace std;


class Student
{
	friend ostream& operator<<(ostream&, Student);
	friend istream& operator>> (istream&, Student&);

private:
	int stuId;
	string name;
	int gpa;

public:
	Student(int, string, int);
	int getStudId();
};

ostream& operator<<(ostream& out, Student stu)
{
	out<<stu.stuId<< " " << stu.name<< " " << stu.gpa<<endl;
	return out;
}

istream& operator >> (istream& in, Student& stu)
{
	in >> stu.stuId >> stu.name >> stu.gpa;
	return in;
}


Student::Student(int id=0, string nm = "", int gpa = 0.0)
{
	this->stuId = id;
	this->name =nm;
	this->gpa = gpa;
}

int Student::getStudId()
{
	return stuId;
}

int main()
{

	const int QUIT = 0;
	int idNum;
	string name;
	int gpa;

	cout <<"Enter student ID number or " << QUIT << " to quit ";
	cin >>idNum;

		cout << "Enter Name ";
		cin >> name;
		cout << "Enter GPA ";
		cin >> gpa;
		Student aStudent(idNum, name, gpa);

	fstream outfile;
	outfile.open("Student3.dat", ios::app |ios::out | ios::binary);

	outfile.write(reinterpret_cast <const char*>(&aStudent), sizeof(Student));
	outfile.flush();
	
	outfile.flush();
	outfile.close();
	system("pause");
	Student aStudent2;
	fstream infile;
	
	infile.open("Student3.dat", ios::in | ios::binary);

	infile.read(reinterpret_cast <char*>(&aStudent2), sizeof(Student));

	//infile.seekg((0 -1) * sizeof(aStudent));

	infile.flush();
	infile.close();


		cout<< aStudent2 << endl;
	
	system("pause");
	return 0;
}

My program run just fine until the end of program, return 0, and it throw this error

First-chance exception at 0x59b4ad4a (msvcp100d.dll) in file reader and writer.exe: 0xC0000005: Access violation reading location 0x002a4d04.
Unhandled exception at 0x59b4ad4a (msvcp100d.dll) in file reader and writer.exe: 0xC0000005: Access violation reading location 0x002a4d04.

May i know what did i do wrong?
Thanks in advance

Attachments Autos.png 23.17 KB call_stack.png 19.57 KB Xutil.png 37 KB

My suggestion is to first create a demo program where there is no user input (hardcode or remove anything that you can to still reproduce the problem). This way we all know exactly what the state of the program is when looking at your code.

David

Why declare gpa as an int and then default it with a value that's either a float or a double?

Why declare and define >> and << and then not use them?

Why use read() and write() instead of >> and <<?

Why are you trying to flush an input stream? flush() is only for output streams.

You cant treat your Student class as a POD type because its not. Thus casting it
to char* is wrong. So these calls are a bug:

outfile.write(reinterpret_cast <const char*>(&aStudent), sizeof(Student));
infile.read(reinterpret_cast <char*>(&aStudent2), sizeof(Student));

Use proper insertion/extraction operators which you defined already!

Edited 6 Years Ago by firstPerson: n/a

In syntatically:
so you got the call stack you asking from us?

Check your destructor , the error happens when it calls the destructor.


In semantically:
Why the hell it gives a access violation when it calls the destructor?
:) well when in the line number 91 the there are 2 student objects to be
destroyed. Both of them contain a two std::string objects as composites , but both
of that two std::string objects have a reference to a one char*, the default way
it will be implemented inside the STL.So when the string destructor tries to
deallocate the same pointer twice it gives the access violation.

to avoid this you can do deep copy instead of the shallow copy.

or just do like this.

Student* aStudent2;
	fstream infile;
	
	infile.open("Student3.dat", ios::in | ios::binary);
        /* going to allocate some memory to aStudent */
        aStudent2= (Student*)new char[sizeof(aStudent)];

	infile.read(reinterpret_cast <char*>(aStudent2), sizeof(Student));

Then this won't be a trouble.Because pointers will not be destructed.

Need more solutions over this?Yes there are.

Edited 6 Years Ago by NicAx64: n/a

My suggestion is to first create a demo program where there is no user input (hardcode or remove anything that you can to still reproduce the problem). This way we all know exactly what the state of the program is when looking at your code.
David

Thanks for replying...

Why declare gpa as an int and then default it with a value that's either a float or a double?

Why declare and define >> and << and then not use them?

Why use read() and write() instead of >> and <<?

Why are you trying to flush an input stream? flush() is only for output streams.

1. because i forgot to remove the decimal when i change it to int.

2. because i use it on the last statement and this is testing purpose..

3. Because i'm a beginner and i dunno how to use one, Care to demo?

4. Because i ran out of idea from that error...

Thanks for helping..

You cant treat your Student class as a POD type because its not. Thus casting it
to char* is wrong. So these calls are a bug:

outfile.write(reinterpret_cast <const char*>(&aStudent), sizeof(Student));
infile.read(reinterpret_cast <char*>(&aStudent2), sizeof(Student));

Use proper insertion/extraction operators which you defined already!

In syntatically:
so you got the call stack you asking from us?

Check your destructor , the error happens when it calls the destructor.


In semantically:
Why the hell it gives a access violation when it calls the destructor?
well when in the line number 91 the there are 2 student objects to be
destroyed. Both of them contain a two std::string objects as composites , but both
of that two std::string objects have a reference to a one char*, the default way
it will be implemented inside the STL.So when the string destructor tries to
deallocate the same pointer twice it gives the access violation.

Sorry lol.. i didn't know such thing as in our college, this is how our professor ("which i doubt his qualification") teaches me...

to avoid this you can do deep copy instead of the shallow copy.

or just do like this.

Student* aStudent2;
	fstream infile;
 
	infile.open("Student3.dat", ios::in | ios::binary);
        /* going to allocate some memory to aStudent */
        aStudent2= (Student*)new char[sizeof(aStudent)];
 
	infile.read(reinterpret_cast <char*>(aStudent2), sizeof(Student));

Then this won't be a trouble.Because pointers will not be destructed.

Need more solutions over this?Yes there are.

Thanks man!!! You solve my problem..
Thanks again.. Care to show the "more solutions" that you just said?

This article has been dead for over six months. Start a new discussion instead.