为什么这段代码表现得很奇怪?

时间:2012-02-19 12:53:45

标签: c++ linux g++

我在C ++中有这个代码,它提供了奇怪的输出:

#include<iostream>
using namespace std;
int main(){
    int r[15]={0};
    int n = 5;
    r[15]=20;
    cout<<n;    
}

输出显然应该是5,但它给了我20.现在我知道r [15]超出界限。这个代码应该为尝试访问r [15]抛出一个异常,不应该吗?但是,它通常用g ++编译并输出错误的输出。我无法弄清楚造成这种异常的原因。有人可以帮忙吗?

仅供参考,这段代码只是一个示例,我不得不从更大的代码中找出这个错误,这花费了我很多时间,否则,如果抛出异常就可以保存。

更新 我检查了以下代码:

#include<iostream>
using namespace std;
int main(){
    int n = 5;
    int r[15]={0};
    r[15]=20;
    cout<<n;
}

Output:
20

我也检查了以下代码:

#include<iostream>
using namespace std;
int main(){
    int n = 5;
    int a=5;
    int r[15]={0};
    r[15]=20;
    cout<<n<<endl<<a;
}

Output:
5
5

因此,如果堆栈说明正确,那么在这种情况下,其中任何一个值都应该被修改,对吧?它没有。

2 个答案:

答案 0 :(得分:9)

由于r是15个元素的数组,r[14]是最后一个元素。因此r[15]=20;是未定义的行为。 C ++不进行边界检查,因此在处理普通数组时不会出现异常。

在您的情况下,r[15]=20碰巧在存储n的精确位置覆盖堆栈。

答案 1 :(得分:5)

  

现在我知道r[15]已经出界了。这段代码应该为尝试访问r[15]而抛出异常,不应该吗?

除非您使用某种检查库,否则不会。 C(和C ++)非常靠近机器,因此您可以适应这种情况。 (这是他们权力的一部分。)在某些编译器上有编译器标志会插入边界检查(以运行时成本),但gcc不执行此操作(您可以找到补丁集将其添加为功能,虽然我认为仅适用于C)。

那里(显然)发生的事情是n变量在r数组的15个插槽之后立即在堆栈上结束:

+-------+
| r[0]  |
| r[1]  |
| r[2]  |
...
| r[13] |
| r[14] |
| n     |
+-------+

...所以写入您的越界条目r[15]最终会覆盖它(在您的特定情况下;这不是您可以或应该依赖的行为,堆栈上的事物的顺序是没有定义为由它们在源中声明的顺序决定,并且可能是。)