【问题标题】:Vector operator [ ] out of range leads to a crash?向量运算符 [ ] 超出范围会导致崩溃?
【发布时间】:2015-11-18 23:02:54
【问题描述】:
vector<int> iV2_func{2, 3, 4, 5};
drucke(iV2_func);
  for (j=0; j<=iV2_func.size(); j++) { 
    iV2_func[j] = quadfunc(iV2_func[j]+1);
 }
 drucke(iV2_func);

我目前正在为即将到来的 C++ 考试练习,由于我是使用 Java 长大的,因此我并不熟悉 C++ 的所有习惯。 给定的代码在 main()-Method 中,所有必要的内容都已包含在内等。 任务是检测六个 for 循环中的错误,这些循环使用不同的方法将参数与自身相乘,例如宏、模板、内联函数等。 drucke() 打印向量的单个成员。 这里的这个 for 循环显然是越界了,但是由于没有使用 .at()-Method,所以不会抛出异常,而是我们最终会出现未定义的行为。

当我启动程序时,程序在打印完所有行之后崩溃。甚至这里的 for 循环 after 的 for 循环也正在运行,并且所有内容都会被打印出来。似乎错误发生在 main() 方法的末尾,而不是在程序访问超出范围的索引时发生,但故障肯定出在该索引上,因为否则程序不会崩溃。那么程序似乎可以使用该代码但最终仍然崩溃的原因是什么?

【问题讨论】:

  • 它有未定义的行为,这意味着任何事情都可能发生。
  • 向量 operator [ ] 超出范围会导致崩溃我知道这会很好!
  • 有错误的代码不会像你预期的那样运行。这就是我们修复错误的原因。
  • @TheParamagneticCroissant 但这种未定义的行为是否恒定?我认为它会一直改变,否则你可以定义它。
  • @Grougal “任何事情都可能发生”包括“它每次都可能执行相同的错误操作”。 “未定义”意味着您不能可能假设任何关于该行为的行为,因此尝试推测它是完全没有意义的。

标签: c++ vector error-handling


【解决方案1】:

那么程序似乎可以使用该代码但最终仍然崩溃的原因是什么?

您很可能已经在调试构建配置中编译了您的程序。在调试构建中,分配的内存区域的“边界”通常填充金丝雀值,以便在内存释放时可以检测到 OOB 写入。当检测到这种被杀死的金丝雀时,内存释放器将中止程序。

为什么需要金丝雀值?因为在现代操作系统上,内存分配和保护只发生在页面粒度上,通常是 4k。因此,只要您的内存访问保持在操作系统提供的映射范围内(这是页面大小的倍数),操作系统就无法检测到非法访问。然而,内存分配器将在这些页面内进行池分配,并且由于在这样一个区域内的对象之间没有保护,因此很难检测到破坏“邻居”的 OOB 访问。因此,金丝雀值,以便在开发中可以报告此类 OOB 访问。

【讨论】:

  • 所以基本上它是一种安全措施,可以检测到某些内容是 OOB 编写的。我想我现在明白了。谢谢!
  • @Grougal:与其说是安全功能,不如说是调试助手。不要依赖这种行为,因为它是定义的实现,只是为了让您意识到代码存在问题。
猜你喜欢
  • 2020-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-29
  • 1970-01-01
  • 2022-11-17
  • 2021-03-07
  • 1970-01-01
相关资源
最近更新 更多