访问其边界之外的数组有多危险(在C中)?有时候我会从数组外部读取(我现在理解我然后访问我的程序的某些其他部分使用的内存,甚至超过它)或者我试图将值设置为数组之外的索引.该程序有时会崩溃,但有时只是运行,只会产生意想不到的结果.
现在我想知道的是,这真的有多危险?如果它损坏我的程序,那就不是那么糟糕了.另一方面,如果它打破了我的程序之外的东西,因为我以某种方式设法访问一些完全不相关的内存,那么它是非常糟糕的,我想.我读了很多"任何可能发生的事情","分割可能是最不好的问题","你的硬盘可能会变成粉红色,独角兽可能会在你的窗下唱歌",这很好,但真正的危险是什么?
我的问题:
我使用OSX 10.7,Xcode 4.6.
我在C++程序中为这样的边界分配值:
#include <iostream>
using namespace std;
int main()
{
int array[2];
array[0] = 1;
array[1] = 2;
array[3] = 3;
array[4] = 4;
cout << array[3] << endl;
cout << array[4] << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
程序打印3和4.应该是不可能的.我正在使用g ++ 4.3.3
这是编译和运行命令
$ g++ -W -Wall errorRange.cpp -o errorRange
$ ./errorRange
3
4
Run Code Online (Sandbox Code Playgroud)
只有在分配时才array[3000]=3000会给我一个分段错误.
如果gcc没有检查数组边界,我怎么能确定我的程序是否正确,因为它可能会导致一些严重的问题?
我用上面的代码替换了
vector<int> vint(2);
vint[0] = 0;
vint[1] = 1;
vint[2] = 2;
vint[5] = 5;
cout << vint[2] << endl;
cout …Run Code Online (Sandbox Code Playgroud) 指针如何指向[-1]数组的索引每次都会产生合法的输出.指针赋值实际发生了什么?
#include<stdio.h>
int main()
{
int realarray[10];
int *array = &realarray[-1];
printf("%p\n", (void *)array);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
代码输出:
manav@workstation:~/knr$ gcc -Wall -pedantic ptr.c
manav@workstation:~/knr$ ./a.out
0xbf841140
Run Code Online (Sandbox Code Playgroud)
编辑:如果这种情况有效,那么我可以用它来定义一个索引从1开始而不是0的数组,即:array [1],array [2],...
int data[8];
data[9] = 1;
Run Code Online (Sandbox Code Playgroud)
c ++标准对此有何评论?这是未定义的行为吗?
至少C编译器(gcc -std = c99 -pedantic -W -Wall)对此没有任何说明.
谢谢.
我有这段代码,它运行得很好,但我不知道为什么:
int main(){
int len = 10;
char arr[len];
arr[150] = 'x';
}
Run Code Online (Sandbox Code Playgroud)
说真的,尝试一下!它有效(至少在我的机器上)!但是,如果我尝试更改索引太大(例如索引 20,000)的元素,它就不起作用。所以编译器显然不够聪明,无法忽略这一行。
那么这怎么可能呢?
答案:我可以用它来写入堆栈上其他变量消耗的内存,如下所示:
#include <stdio.h>
main(){
char b[4] = "man";
char a[10];
a[10] = 'c';
puts(b);
}
Run Code Online (Sandbox Code Playgroud)
输出“可以”。这确实是一件很糟糕的事情。
当我遇到这种情况时,我正在对一个主题进行一些研究.假设以下C代码:
#include <stdio.h>
int main() {
char name[1];
scanf("%s",name);
printf("Hi %s",name);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我编译-fno-stack-protector并使用超过1的输入进行测试,就像John,令我惊讶的是,它的工作原理!
当输入长于1时,它不应该抛出分段错误吗?
最终它打破了Alexander输入(9),但它适用于任何小于9的内容.
为什么它的输入长于名称数组长度?
PS:我使用Ubuntu(64位),gcc版本4.8.4(Ubuntu 4.8.4-2ubuntu1~14.04)和CLion作为IDE.
基本上,我在课堂上遇到过这段代码:
#include <stdio.h>
int main() {
int arr[3][3] = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
printf("%d", arr[0][2]);
printf("\n%d", arr[1][0]);
printf("\n%d", arr[0][2 + 1]);
}
Run Code Online (Sandbox Code Playgroud)
我有点困惑,因为最后一个printf语句arr[0][2 + 1]等于arr[0][3],但由于我们的数组维度是 3x3,所以这使得我们的最大索引值仅为 2,从而arr[0][3]超出范围。但是当我运行这个东西时,它显示4,这与第二条语句相同printf,即arr[1][0],为什么会发生这种情况?
我期待类似的错误,它会告诉我它超出了范围,但它继续打印数组的下一个索引值。
我正在尝试这段代码,
#include <stdio.h>
main(){
int a[2],i;
a[5] = 12;
for(i=0;i<10;i++){
printf("%d\n", a[i]);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它给了我输出:
1053988144
32767
0
3
0
12
-1267323827
32716
0
0
Run Code Online (Sandbox Code Playgroud)
为什么[5]可以访问?不应该通过RunTime错误吗?
我有以下C++示例代码,我的想法是它在LINE II抛出运行时错误.
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
void printer(int i) {
cout << i << ", ";
}
int main() {
int mynumbers1[]={3, 9, 0, 2};
int mynumbers2[]={6, 1, 4, 5};
vector<int> v1(7);
sort(mynumbers2, mynumbers2 + 4);
sort(mynumbers1, mynumbers1 + 4);//LINE I
merge(mynumbers1, mynumbers1+5, mynumbers2, mynumbers2+5, v1.begin());//LINE II
for_each(v1.begin(), v1.end(), printer);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但是,该程序的输出实际上是:
0, 1, 2, 3, 4, 5, 6,
Run Code Online (Sandbox Code Playgroud)
如果我改变,例如,合并的第二个参数,mynumbers1+6那么我得到一个运行时错误:
*** Error in `./program': free(): invalid next size (fast): 0x0000000002468010 *** …Run Code Online (Sandbox Code Playgroud) 这是我的最小可重现示例:
#include <stdio.h>
int main( int argc, char* argv[])
{
printf (" this is the contents of argc:%d\n",argc);
int i;
for (i = 0; i < argc ; i++){
printf(" argv = %d = %s\n",i,argv[i]);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当我argc将 for 循环更改为数字时,比方说10,代码在到达之前崩溃10:
$ ./argc one two three
this is the contents of argc:4
argv = 0 = ./argc
argv = 1 = one
argv = 2 = two
argv = 3 = three
argv …Run Code Online (Sandbox Code Playgroud)