我在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
因此,如果堆栈说明正确,那么在这种情况下,其中任何一个值都应该被修改,对吧?它没有。
答案 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]
最终会覆盖它(在您的特定情况下;这不是您可以或应该依赖的行为,堆栈上的事物的顺序是没有定义为由它们在源中声明的顺序决定,并且可能不是。)