我在一个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;
}

程序输出3和4。这应该是不可能的。我使用g++ 4.3.3

下面是编译和运行命令

$ g++ -W -Wall errorRange.cpp -o errorRange
$ ./errorRange
3
4

只有当分配数组[3000]=3000时,它才会给我一个分割错误。

如果gcc不检查数组边界,我怎么能确定我的程序是正确的,因为它可能导致一些严重的问题以后?

我将上面的代码替换为

vector<int> vint(2);
vint[0] = 0;
vint[1] = 1;
vint[2] = 2;
vint[5] = 5;
cout << vint[2] << endl;
cout << vint[5] << endl;

这个也不会产生误差。


当前回答

当你声明int数组[2];您保留了2个内存空间,每个空间4个字节(32位程序)。 如果你在代码中输入数组[4],它仍然对应一个有效的调用,但只有在运行时它才会抛出一个未处理的异常。c++使用手动内存管理。这实际上是一个用于黑客程序的安全漏洞

这有助于理解:

某个指针;

somepointer [0] = somepointer [5];

其他回答

不明确的行为对你有利。不管你要破坏的是什么内存,显然都没有任何重要的东西。注意,C和c++不对数组进行边界检查,因此在编译或运行时不会捕获类似的东西。

当然,您正在重写堆栈,但是程序非常简单,因此不会注意到这种影响。

当你用C语言写'array[index]'时,它会把它转换成机器指令。

翻译是这样的:

获取数组的地址 获取数组所包含对象类型的大小 '将类型大小乘以索引' '将结果添加到数组地址' '读取结果地址中的内容'

结果处理的内容可能是数组的一部分,也可能不是数组的一部分。为了换取机器指令的惊人速度,你失去了计算机为你检查事物的安全网。如果你一丝不苟,小心谨慎,这不是问题。如果你粗心大意或犯了错误,你就会被烧伤。有时它可能会生成导致异常的无效指令,有时则不会。

The behavior can depend on your system. Typically, you will have a margin for out of bounds, sometimes with value of 0 or garbage values. For the details you can check with memory allocation mechanism used in your OS. On top of that, if you use the programming language like c/c++, it will not check the bounds when you using some containers, like array. So, you will meet "undefined event" because you do not know what the OS did below the surface. But like the programming language Java, it will check the bound. If you step outside of the bound, you will get an exception.

据我所知,这是没有定义的行为。用它运行一个更大的程序,它会在某个地方崩溃。边界检查不是原始数组(甚至std::vector)的一部分。

使用std::vector和std::vector::iterator's来代替,这样你就不用担心了。

编辑:

只是为了好玩,运行这个,看看你多久会崩溃:

int main()
{
   int arr[1];

   for (int i = 0; i != 100000; i++)
   {
       arr[i] = i;
   }

   return 0; //will be lucky to ever reach this
}

Edit2:

不要运行它。

Edit3:

好的,下面是一个关于数组及其与指针关系的快速课程:

当你使用数组索引时,你实际上是在使用一个伪装的指针(称为“引用”),它是自动解引用的。这就是为什么数组[1]自动返回该下标处的值而不是*(array+1)。

当你有一个指向数组的指针时,像这样:

int arr[5];
int *ptr = arr;

然后,第二个声明中的“array”实际上衰减为指向第一个数组的指针。这和下面的行为是等价的:

int *ptr = &arr[0];

当你试图访问超出你所分配的内存时,你实际上只是使用了一个指向其他内存的指针(这一点c++不会抱怨)。以我上面的示例程序为例,这相当于:

int main()
{
   int arr[1];
   int *ptr = arr;

   for (int i = 0; i != 100000; i++, ptr++)
   {
       *ptr++ = i;
   }

   return 0; //will be lucky to ever reach this
}

编译器不会抱怨,因为在编程中,你经常需要与其他程序通信,尤其是操作系统。这是通过指针完成的。