繁体   English   中英

每隔几次尝试运行我的构建,我就会遇到分段错误。 我不明白为什么

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM