访问超出范围的索引时的矢量异常数



I下面的代码演示了当试图访问矢量中的超范围索引时的奇怪行为

#include <iostream>
#include <vector>
int main()
{
    std::vector<int> a_vector(10, 0);
    for(int i = 0; i < a_vector.size(); i++)
    {
        std::cout << a_vector[i] << ", ";
    }
    for(int j = 0; j <= a_vector.size(); j++)
    {
        std::cout << a_vector[i] << ", ";
    }
    return 0;
}

第一个for循环产生预期的0, 0, 0, 0, 0, 0, 0, 0, 0, 0,输出,但是第二个循环产生0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1318834149,

第二个循环产生的最后一个数字在每次运行代码时都会发生变化,并且总是很大,除非向量的长度在3到7之间(包括3和7(,在这种情况下,最后一个数是0。对于更大的索引,它也会持续存在——例如,将第二个循环的停止值修改为j <= a_vector.size() + 2000,直到索引1139,它才返回到0。

这个数字从哪里来,它有什么意义吗?最重要的是,为什么代码没有抛出"超出范围"错误,这是我希望它在被要求访问向量的第11个元素时会做的10个元素长的

你是说?

for(int j = 0; j < a_vector.size(); j++)
{
    std::cout << a_vector[j] << ", ";
}

因为你超出了向量范围,wich是一个未定义的行为,每次运行它时都会返回一个"随机"数。

C++是强大的,强大的力量带来巨大的责任。如果你超出范围,它会让你。99.99999999%的时间这不是一件好事,但它仍然可以让你做到。

至于为什么它每次都会改变,计算机将数组结束后的大块内存视为另一个int,然后将其显示出来。该int的值取决于上次使用时内存中剩下的位。它可能用于程序早期分配和丢弃的字符串,可能是编译器在内存分配中插入的填充以优化访问,可能是另一个对象正在使用的活动内存。如果你不知道(就像本例中那样(,你就没有办法知道,也不应该期望有任何一致的行为。

(你可能会问,0.00000000001%是什么?什么时候它是一件好事?有一次我故意超出子类中数组的范围,访问父类中没有访问器来修复错误的一些私有数据。这是在一个我无法控制的库中,所以我不得不这样做,或者忍受错误。也许这不是一件好事,但因为我对其中的内存布局很有信心它在特定的案例中发挥了作用。(

附录:我提到的这个案例是对糟糕情况的务实解决方案。代码需要发货,而供应商几个月内都不会修复错误。尽管我对这种行为很有信心(我知道确切的目标平台,代码是静态链接的,所以不会被用户替换,等等(,但这引入了代码的脆弱性和对未来的新责任。也就是说,下次更新库时,它几乎肯定会崩溃。

所以我评论了代码的细节,解释了确切的问题,我在做什么,以及什么时候应该删除它。我在承诺信中也用了很多大写字母。我告诉了所有其他程序员,以防在修复错误之前我被公交车撞了。换言之,我行使了行使这一巨大权力所需的巨大责任。

最新更新