我在C++中有这个代码,它给出了奇怪的输出:
#include<iostream>
using namespace std;
int main(){
int r[15]={0};
int n = 5;
r[15]=20;
cout<<n;
}
Run Code Online (Sandbox Code Playgroud)
输出显然应该是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
Run Code Online (Sandbox Code Playgroud)
我也检查了以下代码:
#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
Run Code Online (Sandbox Code Playgroud)
因此,如果堆栈说明正确,那么在这种情况下,其中任何一个值都应该被修改,对吧?它没有.
由于r是15个元素的数组,因此r[14]是最后一个元素.因此r[15]=20;是未定义的行为.C++不进行边界检查,因此在处理普通数组时不会出现异常.
在您的情况下,r[15]=20恰好在n存储的精确位置覆盖堆栈.
现在我知道
r[15]是出界的.这段代码应该为尝试访问而抛出异常r[15],不应该吗?
除非您使用某种检查库,否则不会.C(和C++)非常接近机器,所以你可以让自己处于这种情况.(这是他们权力的一部分.)在某些编译器上有编译器标志会插入边界检查(以运行时成本),但gcc不执行(您可以找到补丁集将其添加为功能,但我认为仅适用于C).
那里(显然)发生的事情是你的n变量在r数组的15个插槽之后立即在堆栈上结束:
+-------+ | r[0] | | r[1] | | r[2] | ... | r[13] | | r[14] | | n | +-------+
...所以写入您的越界条目r[15]最终会覆盖它(在您的特定情况下;这不是您可以或应该依赖的行为,堆栈上的事物的顺序未定义为由订单确定它们在源中被声明,并且可能不是).