[英]Every few attempts to run my build, I get a segmentation fault. I dont understand why
所以我得到一个 Segmentation fault: 11 错误,我知道是哪个块导致它,但我试图理解为什么。
std::vector<Entity> grassEntities;
for (int i = 0; i < 40; i++) {
grassEntities.push_back(Entity(i * 32, 592, grassTexture));
}
std::vector<Entity> dirtEntities;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 41; j++) {
dirtEntities.push_back(Entity(j * 32, (688 - (i * 32)), dirtTexture));
}
}
bool gameRunning = true;
SDL_Event event;
while (gameRunning) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT)
gameRunning = false;
}
window.clear();
std::vector<Entity>::iterator it;
std::vector<Entity>::iterator it2;
for (it = dirtEntities.end(); it >= dirtEntities.begin(); it--){
window.render(*it);
}
for (it2 = grassEntities.end(); it2 >= grassEntities.begin(); it2--){
window.render(*it2);
}
window.display();
}
这个问题在于本节
for (it2 = grassEntities.end(); it2 >= grassEntities.begin(); it2--){
window.render(*it2);
}
这对我来说很奇怪,因为这部分似乎工作得很好:
for (it = dirtEntities.end(); it >= dirtEntities.begin(); it--){
window.render(*it);
}
在游戏循环内部,在两个for
循环的第一次迭代中, it
等于dirtEntities.end()
, it2
等于grassEntities.end()
。 取消引用end
迭代器是未定义的行为。 代码没有崩溃的事实只是“幸运”。
如果要反向迭代,请改用反向迭代器:
for (auto it = dirtEntities.rbegin(); it != dirtEntities.rend(); it++){
window.render(*it);
}
for (auto it2 = grassEntities.rbegin(); it2 != grassEntities.rend(); it2++){
window.render(*it2);
}
.end()
返回的迭代器是不可延迟的。 循环应重写为
for (auto it = dirtEntities.end(); it != dirtEntities.begin();)
{
--it;
// ...
}
了解如何在编译器中启用迭代器调试。 可以自动检测到这些错误。
vector 的 end() 方法返回一个迭代器,该迭代器引用容器中的最后一个元素。
从这个迭代器中读取值不是最佳实践。
如果你想读取最后一个元素的值,你应该使用 reverse_iterator。
std::vector<int>::reverse_iterator rit = myvector.rbegin();
rbegin() 将迭代器返回到容器内的最后一个元素。
对我来说很奇怪,因为这部分工作得很好:
不,该程序具有未定义的行为,这意味着即使它没有明确说明并且“似乎正在工作”,它仍然是错误的。 这是因为对于第一次迭代,您要取消引用it
,它是调用end
返回的迭代器。
//------------vvv---->undefined behavior for the first iteration
window.render(*it);
未定义的行为意味着任何事情1都可能发生,包括但不限于给出预期输出的程序。 但永远不要依赖(或基于)具有未定义行为的程序的输出。 该程序可能会崩溃。
所以你看到的输出(也许看到)是未定义行为的结果。 正如我所说,不要依赖具有 UB 的程序的输出。 该程序可能会崩溃。
因此,使程序正确的第一步是删除 UB。 只有这样,您才能开始推理程序的输出。
1有关未定义行为的更技术上准确的定义,请参见此处,其中提到:对程序的行为没有限制。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.