Jump to content
  • Advertisement
Sign in to follow this  
Ripiz

[VC++] Reading file problem

This topic is 3250 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I've got problem with reading file.
//structure
struct PlayerData{
	string account;
	string pass;
	string char1;
	string char2;
	PlayerData(){
		account="";
		pass="";
		char1="";
		char2="";
	}
};

//code
void Login(int index, string id, SystemAddress IP, string Dacc, string Dpass){
	if(GetIndex(id)>=0) return;
	string acc="data/players/"+Dacc;
	string pass=Dpass;
	PlayerData pdata;
	ifstream myFileRead (acc.c_str(), ios::in | ios::binary);
	if(myFileRead){
		myFileRead.read ((char*)&pdata, sizeof (PlayerData)); // MARK
		//reading data
		myFileRead.close();
	}else{
		ofstream myFileWrite (acc.c_str(), ios::out | ios::binary);
		pdata.account=Dacc;
		pdata.pass=pass;
		myFileWrite.write((char*)&pdata, sizeof (PlayerData));
		myFileWrite.close();
	}
} //error here
Error stops appearing when I comment out line {MARK} If anymore details needed, just let me know.

Share this post


Link to post
Share on other sites
Advertisement
It's not compile error, but execution.
It throws
First-chance exception at 0x54df9c54 (msvcp100d.dll) in Server.exe: 0xC0000005: Access violation writing location 0x54a40202.
Unhandled exception at 0x54df9c54 (msvcp100d.dll) in Server.exe: 0xC0000005: Access violation writing location 0x54a40202.
at other place, but Call Stack leads to that line.

Share this post


Link to post
Share on other sites
When you are reading into your PlayerData instance (pdata), you are overwriting the internal structure of (at least some of) the string typed members of the PlayerData struct. The error occurs most probably when the (autogenerated) destructor for PlayerData executes (which happens when the pdata variable goes out of scope), and this destructor in turn calls the string destructors. The string destructors try to perform cleanup operations on their instance state (releasing memory etc), which you've overwritten before.


Edit:

The problem is that PlayerData and string are classes, not raw char arrays. You must properly read data into each string variable. You can use the '>>' operators of ifstream for that.

struct PlayerData {
// ...
void read(ifstream& stream) {
stream >> this->account;
stream >> this->pass;
// ...
}
};

void Login() {
// ...
pdata.read(myFileRead);
//
}






[Edited by - Konfusius on October 27, 2009 2:36:19 PM]

Share this post


Link to post
Share on other sites
You can't read/write std::string objects (in PlayerData) as if they were binary blobs like that. You are basically filling them with garbage and then when the destructor for PlayerData runs you blow up trying to dereference a bad pointer. You have to read each string individually and assign it to the appropriate member.

As an aside, std::string objects default-initialize to "". Your PlayerData constructor isn't doing anything useful, even after putting aside the whole thing about initializing in the body rather than using an initializer list.

Share this post


Link to post
Share on other sites
[Konfusius] Hm... Well it seems to match Call Stack which goes through deconstructors. How can I fix it? I'm not sure

[Anon Mike] It used to be fine the way I read it, but now for some reason it broke 0.o Not sure why

Share this post


Link to post
Share on other sites
Quote:
[Konfusius] Hm... Well it seems to match Call Stack which goes through deconstructors. How can I fix it? I'm not sure

See my edit for a more proper way.

Quote:
[Anon Mike] It used to be fine the way I read it, but now for some reason it broke 0.o Not sure why

If it worked before, it was coincedence. You're storing strings which contain dynamically generated pointers, which point to memory that was allocated to your program at the time when it was running the last time. The next run, when you read the data, your program may be loaded at an entirely different adress and its dynamic memory range (the heap) is also elsewhere. Which leads to crashes when you try to access the old memory locations.

Share this post


Link to post
Share on other sites
struct PlayerData{
string account;
string pass;
string char1;
string char2;
PlayerData(){
account="";
pass="";
char1="";
char2="";
}
void read(ifstream& stream) {
stream >> account;
stream >> pass;
stream >> char1;
stream >> char2;
}
void write(ofstream& stream) {
stream << account;
stream << pass;
stream << char1;
stream << char2;
}

};


I made something wrong, string is merged into one. Why this happens? I though it has null byte in the end to mark where string ends

Share this post


Link to post
Share on other sites
Thank you, works good :)
But I have one question for future

//If I write like this:
stream << [string] << endl;
stream << [string] << endl;
stream << [int];
stream << [unsigned int];
stream << [float];

//to read it properly, it will be like this?
stream >> [string];
stream >> [string];
stream >> [int];
stream >> [unsigned int];
stream >> [float];

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!