C++ - 对具有 std::sort 的结构向量进行排序会导致读取访问冲突
C++ - Sorting vector of structs with std::sort results in read access violation
我对 std::sort 方法有疑问。在下面的代码中,我使用 std::sort 方法对结构向量(= Highscore)进行排序。但是,当我 运行 这一行时,xmemory 文件中会抛出一个 "read access violation" 异常。
详情如下:
抛出异常:读取访问冲突。
_Pnext 是 0x217AE3EE9D8。发生
这是错误发生的方法。
void HighscoreManager::sortAndChangeRanks(bool deleteLast) {
std::sort(_highscores.begin(), _highscores.end());
if (deleteLast && _highscores.size() > MaxHighscores) {
_highscores.pop_back();
}
for (int i = 0; i < _highscores.size(); i++) {
_highscores.at(i).rank = i + 1;
}
}
_highscores 定义为 std::vector<Highscore> _highscores;
并在方法调用之前填充了文件中的值。这很好用。当我在使用排序方法之前进行调试时,向量中会填充文件中的正确值。
这是高分结构的实现:
struct Highscore {
int rank;
std::string name;
int points;
Highscore() {}
Highscore(int r, std::string n, int p) : rank(r), name(std::move(n)), points(p) {}
bool operator<(const Highscore& h1) const {
return points < h1.points;
}
};
请帮助我或指出错误所在的方向,我没有想法。
编辑
由于在调用 std::sort 之前在评论中询问了向量在哪里使用,因此这是从对象构造函数调用的方法,并且是唯一一次在排序之前使用向量。这种从二进制文件读取(写入工作类似)的方式是基于 .
bool HighscoreManager::loadFromFile() {
std::ifstream in(FileName, std::ios::in | std::ios::binary);
if(!in) {
return false;
}
try {
std::vector<Highscore>::size_type size = 0;
in.read((char*)&size, sizeof(size));
_highscores.resize(size);
in.read((char*)&_highscores[0], _highscores.size() * sizeof(Highscore));
} catch(const std::exception& e) {
std::cout << e.what() << std::endl;
}
in.close();
sortAndChangeRanks(false);
return in.good();
}
不知道你们的高分存储“优化”了什么。这似乎只是白费力气。您不会存储数百万的高分。您可以将它们存储为文本。 “优化”无法在正常使用中衡量。如果您认为自己正在优化:显示测量结果。否则你就是在自欺欺人,浪费时间。
最重要的是,您已将代码复杂化到 运行 成为一个需要很长时间调试的问题。那是一种学习经历,但严格来说,你因此浪费了更多时间。在大多数情况下,您的时间比运行时间花费更多。
您所需要的只是可以在两分钟内完成的琐碎文本流 I/O。如果您不完全了解正在发生的事情,则不建议您随意使用二进制存储。就目前而言,如果您尝试读取在具有不同字节顺序的机器上编写的高分,您的代码将会崩溃或更糟。现在你必须管理所有数字数据的字节序……祝你好运。
无论如何,这实际上是一种悲观情绪,因为您不断地重新分配临时字符串缓冲区。不需要那个缓冲区。您应该调整字符串本身的大小并将数据放入其中。
std::string name(nLen);
in.read(&name[0], name.size());
这是我目前使用的解决方案。这对我有用并解决了我的问题,即 reading/writing 和 std::string 到二进制文件而不是排序方法(感谢对问题的评论!)。为了解决这个问题,我使用了 this.
的部分内容
正在从文件中读取:
std::ifstream in(FileName, std::ios::in | std::ios::binary);
if(!in) {
return false;
}
try {
std::vector<Highscore>::size_type size = 0;
in.read((char*)&size, sizeof(size));
for(int i = 0; i < size; i++) {
int r, p;
size_t nLen;
in.read((char*)&r, sizeof(int));
in.read((char*)&p, sizeof(int));
in.read((char*)&nLen, sizeof(size_t));
char* temp = new char[nLen + 1];
in.read(temp, nLen);
temp[nLen] = '[=10=]';
std::string name = temp;
delete[] temp;
_highscores.emplace_back(r, name, p);
}
} catch(const std::exception& e) {
std::cout << e.what() << std::endl;
}
in.close();
sortAndChangeRanks(false);
return in.good();
}
写入文件:
bool HighscoreManager::saveToFile() {
std::ofstream out(FileName, std::ios::out | std::ios::binary);
if(!out) {
return false;
}
std::vector<Highscore>::size_type size = _highscores.size();
try {
out.write((char*)&size, sizeof(size));
for(int i = 0; i < size; i++) {
out.write((char*)&_highscores.at(i).rank, sizeof(int));
out.write((char*)&_highscores.at(i).points, sizeof(int));
size_t nameLen = _highscores.at(i).name.size();
out.write((char*)&nameLen, sizeof(size_t));
out.write((char*)_highscores.at(i).name.c_str(), nameLen);
}
} catch (const std::exception& e) {
std::cout << e.what() << std::endl;
}
out.close();
return out.good();
}
谢谢大家的帮助!
我对 std::sort 方法有疑问。在下面的代码中,我使用 std::sort 方法对结构向量(= Highscore)进行排序。但是,当我 运行 这一行时,xmemory 文件中会抛出一个 "read access violation" 异常。
详情如下: 抛出异常:读取访问冲突。 _Pnext 是 0x217AE3EE9D8。发生
这是错误发生的方法。
void HighscoreManager::sortAndChangeRanks(bool deleteLast) {
std::sort(_highscores.begin(), _highscores.end());
if (deleteLast && _highscores.size() > MaxHighscores) {
_highscores.pop_back();
}
for (int i = 0; i < _highscores.size(); i++) {
_highscores.at(i).rank = i + 1;
}
}
_highscores 定义为 std::vector<Highscore> _highscores;
并在方法调用之前填充了文件中的值。这很好用。当我在使用排序方法之前进行调试时,向量中会填充文件中的正确值。
这是高分结构的实现:
struct Highscore {
int rank;
std::string name;
int points;
Highscore() {}
Highscore(int r, std::string n, int p) : rank(r), name(std::move(n)), points(p) {}
bool operator<(const Highscore& h1) const {
return points < h1.points;
}
};
请帮助我或指出错误所在的方向,我没有想法。
编辑
由于在调用 std::sort 之前在评论中询问了向量在哪里使用,因此这是从对象构造函数调用的方法,并且是唯一一次在排序之前使用向量。这种从二进制文件读取(写入工作类似)的方式是基于
bool HighscoreManager::loadFromFile() {
std::ifstream in(FileName, std::ios::in | std::ios::binary);
if(!in) {
return false;
}
try {
std::vector<Highscore>::size_type size = 0;
in.read((char*)&size, sizeof(size));
_highscores.resize(size);
in.read((char*)&_highscores[0], _highscores.size() * sizeof(Highscore));
} catch(const std::exception& e) {
std::cout << e.what() << std::endl;
}
in.close();
sortAndChangeRanks(false);
return in.good();
}
不知道你们的高分存储“优化”了什么。这似乎只是白费力气。您不会存储数百万的高分。您可以将它们存储为文本。 “优化”无法在正常使用中衡量。如果您认为自己正在优化:显示测量结果。否则你就是在自欺欺人,浪费时间。
最重要的是,您已将代码复杂化到 运行 成为一个需要很长时间调试的问题。那是一种学习经历,但严格来说,你因此浪费了更多时间。在大多数情况下,您的时间比运行时间花费更多。
您所需要的只是可以在两分钟内完成的琐碎文本流 I/O。如果您不完全了解正在发生的事情,则不建议您随意使用二进制存储。就目前而言,如果您尝试读取在具有不同字节顺序的机器上编写的高分,您的代码将会崩溃或更糟。现在你必须管理所有数字数据的字节序……祝你好运。
无论如何,这实际上是一种悲观情绪,因为您不断地重新分配临时字符串缓冲区。不需要那个缓冲区。您应该调整字符串本身的大小并将数据放入其中。
std::string name(nLen);
in.read(&name[0], name.size());
这是我目前使用的解决方案。这对我有用并解决了我的问题,即 reading/writing 和 std::string 到二进制文件而不是排序方法(感谢对问题的评论!)。为了解决这个问题,我使用了 this.
的部分内容正在从文件中读取:
std::ifstream in(FileName, std::ios::in | std::ios::binary);
if(!in) {
return false;
}
try {
std::vector<Highscore>::size_type size = 0;
in.read((char*)&size, sizeof(size));
for(int i = 0; i < size; i++) {
int r, p;
size_t nLen;
in.read((char*)&r, sizeof(int));
in.read((char*)&p, sizeof(int));
in.read((char*)&nLen, sizeof(size_t));
char* temp = new char[nLen + 1];
in.read(temp, nLen);
temp[nLen] = '[=10=]';
std::string name = temp;
delete[] temp;
_highscores.emplace_back(r, name, p);
}
} catch(const std::exception& e) {
std::cout << e.what() << std::endl;
}
in.close();
sortAndChangeRanks(false);
return in.good();
}
写入文件:
bool HighscoreManager::saveToFile() {
std::ofstream out(FileName, std::ios::out | std::ios::binary);
if(!out) {
return false;
}
std::vector<Highscore>::size_type size = _highscores.size();
try {
out.write((char*)&size, sizeof(size));
for(int i = 0; i < size; i++) {
out.write((char*)&_highscores.at(i).rank, sizeof(int));
out.write((char*)&_highscores.at(i).points, sizeof(int));
size_t nameLen = _highscores.at(i).name.size();
out.write((char*)&nameLen, sizeof(size_t));
out.write((char*)_highscores.at(i).name.c_str(), nameLen);
}
} catch (const std::exception& e) {
std::cout << e.what() << std::endl;
}
out.close();
return out.good();
}
谢谢大家的帮助!