I am reading a structure named "Highscore" from a binary file. I print the read data in the console and it looks fine. After that, I insert them into a vector with the push_back method and when I'm done, I return the vector.
After the return line, I get the following error (translated from French): "Exception not handled at 0x00007FF6223FF017 in Project1.exe : 0xC0000005 : access violation while reading from 0xFFFFFFFFFFFFFFFF.".
Here is my code:
struct Highscore{
string username;
int points;
};
vector<Highscore> ReadFromHighscores(){
fstream highscoresFiles;
highscoresFiles.open("highscores.db", ios::in | ios::out | ios::binary | ios::app);
highscoresFiles.seekg(0);
Highscore output;
vector<Highscore> highscores;
highscoresFiles.read(reinterpret_cast<char *>(&output), sizeof(Highscore));
cout << "Read : " << output.points << output.username << endl;
Highscore temp;
temp.points = output.points;
temp.username = output.username;
if (!highscoresFiles.eof()) {
highscores.push_back(temp);
}
highscoresFiles.close();
return highscores;
}
As having been pointed out, std::string
contains a char*
(which you are saving and restoring) to the real data. The actual data is not saved and the pointer you restore is causing the crash. To fix that you can create operators for streaming to/from files and dump the username
c-string (including the terminating \0
) and then write the points
int raw. This should work as long as your usernames don't contain \0
in the middle of the string (unusual but valid).
#include <iostream>
#include <iomanip>
#include <vector>
#include <fstream>
struct Highscore{
std::string username;
int points;
Highscore(const std::string& n, int p) : username(n), points(p) {}
Highscore() : Highscore("",0) {}
// operator to save a Highscore to file
friend std::ofstream& operator<<(std::ofstream&, const Highscore&);
// operator to read a Highscore from file
friend std::ifstream& operator>>(std::ifstream&, Highscore&);
// operator to print a Highscore on other ostreams (like std::cout)
friend std::ostream& operator<<(std::ostream&, const Highscore&);
};
std::ofstream& operator<<(std::ofstream& os, const Highscore& hs) {
os.write(hs.username.c_str(), hs.username.size()+1);
os.write(reinterpret_cast<const char*>(&hs.points), sizeof(hs.points));
return os;
}
std::ifstream& operator>>(std::ifstream& is, Highscore& hs) {
std::getline(is, hs.username, '\0');
is.read(reinterpret_cast<char*>(&hs.points), sizeof(hs.points));
return is;
}
std::ostream& operator<<(std::ostream& os, const Highscore& hs) {
os << std::setw(15) << std::left << hs.username << std::setw(8) << std::right << hs.points;
return os;
}
int main() {
// create "highscores.db"
{
std::vector<Highscore> highscores {
{"MadBrother33", 234234},
{"Barny", 14234},
{"Bart", 1434}
};
std::ofstream out("highscores.db", std::ios::binary);
for(auto& hs : highscores) {
out << hs;
}
}
// read "highscores.db"
{
std::vector<Highscore> highscores;
{
Highscore hs;
std::ifstream in("highscores.db", std::ios::binary);
while(in>>hs) {
highscores.emplace_back(std::move(hs));
}
}
for(auto& hs : highscores) {
std::cout << hs << "\n";
}
}
}
Output
MadBrother33 234234
Barny 14234
Bart 1434
User contributions licensed under CC BY-SA 3.0