Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在边界外访问数组不会出错,为什么? 我在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; } int arr[5]; int *ptr = arr;_C++_Arrays - Fatal编程技术网

在边界外访问数组不会出错,为什么? 我在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; } int arr[5]; int *ptr = arr;

在边界外访问数组不会出错,为什么? 我在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; } int arr[5]; int *ptr = arr;,c++,arrays,C++,Arrays,只有当分配数组[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; vectorv

只有当分配
数组[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;
vectorvint(2);
vint[0]=0;
vint[1]=1;
vint[2]=2;
vint[5]=5;

coutg++不检查数组边界,您可能会用3,4覆盖某些内容,但没有什么真正重要的内容,如果您尝试使用更高的数字,您将遇到崩溃

您只是覆盖堆栈中未使用的部分,您可以继续,直到到达为堆栈分配的空间的末尾,它最终会崩溃

编辑:
你没有办法解决这个问题,也许静态代码分析器可以揭示这些故障,但这太简单了,你可能有类似的(但更复杂的)故障,即使是静态分析器也无法检测到,据我所知,这是未定义的行为。用它运行一个更大的程序,它会在某个地方崩溃。边界检查不是原始数组(甚至不是std::vector)的一部分

将std::vector与
std::vector::迭代器一起使用,这样您就不必担心它了

编辑:

只是为了好玩,运行此命令,看看你会崩溃多久:

int main()
{
   int arr[1];

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

   return 0; //will be lucky to ever reach this
}
编辑2:

别跑那个

编辑3:

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

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

当您有一个指向数组的指针时,如下所示:

#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;
}
int arr[5];
int *ptr = arr;
然后,第二个声明中的“数组”实际上正在衰减为指向第一个数组的指针。这相当于以下行为:

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
}

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

您肯定在覆盖堆栈,但程序非常简单,不会引起注意。

欢迎来到每个C/C++程序员最好的朋友:未定义的行为

由于各种原因,语言标准中有很多地方没有规定。这是其中之一

一般来说,每当您遇到未定义的行为时,任何事情都可能发生。应用程序可能会崩溃,可能会冻结,可能会弹出CD-ROM驱动器,或者让恶魔从你的鼻子里出来。它可能会格式化你的硬盘,或者将你所有的色情作品通过电子邮件发送给你的祖母

如果你真的不走运,它甚至可能看起来工作正常

该语言只是说明如果访问数组边界内的元素,应该发生什么。如果你越界,会发生什么,这是没有定义的。它可能在今天工作,在编译器上,但它不是合法的C或C++,并且不能保证它下次运行程序时仍然有效。或者它甚至现在还没有覆盖基本数据,您只是还没有遇到它将导致的问题

至于为什么没有边界检查,答案有几个方面:

  • 数组是C语言的剩余部分。C语言的数组是最基本的。只是具有连续地址的元素序列。没有边界检查,因为它只是公开原始内存。在C语言中实现健壮的边界检查机制几乎是不可能的
  • 在C++中,类类型的边界检查是可能的。但是数组仍然是与C兼容的普通数组。这不是一门课。此外,C++还建立在另一个规则上,使得边界检查非理想。C++的指导原则是“你不为你不使用的东西付费”。如果您的代码是正确的,您就不需要边界检查,也不应该被迫支付运行时边界检查的开销 + C++提供了<代码> STD::vector < /Cord>类模板,这允许两者都具有.<代码>操作员[]
旨在提高效率。语言标准不要求它执行边界检查(尽管它也不禁止)。向量还有
at()
成员函数,保证执行边界检查。所以在C++中,如果使用向量,你将得到最好的两个世界。您可以在不进行边界检查的情况下获得类似数组的性能,并且可以在需要时使用边界检查访问

C或C++将不检查数组访问的界限。< /P> 您正在堆栈上分配数组。通过

array[3]
对数组进行索引相当于*
(array+3)
,其中array是指向&array[0]的指针。这将导致未定义的行为

在C语言中捕捉这种的一种方法是使用静态检查器,例如夹板。如果您运行:

splint +bounds array.c
在,

然后您将得到警告:

array.c:(在函数main中) 数组c:5:9:可能超出范围 商店: 数组[1] 无法解析约束: 需要0>=1 需要满足以下前提条件: 需要maxSet(array@array.c:5:9)>=1可以进行内存写入 写信到电话号码以外的地址 已分配的缓冲区


未定义的行为对您有利。不管你的记忆是什么,显然都没有什么重要的东西。请注意,C和C++不做数组的边界检查,所以这样的东西不会在编译或运行时被捕获。p> 运行此命令,您可能会看到一个错误

正如Falaina指出的那样,valgrind没有这样做
g++ --stack-check -W -Wall errorRange.cpp -o errorRange
valgrind ./errorRange
> g++ -o t -fstack-protector-all t.cc
> ./t
3
4
/bin/bash: line 1: 15450 Segmentation fault      ./t
#include <iostream>
#include <boost/array.hpp>
int main()
{
    boost::array<int,2> array;
    array.at(0) = 1; // checking index is inside range
    array[1] = 2;    // no error check, as fast as int array[2];
    try
    {
       // index is inside range
       std::cout << "array.at(0) = " << array.at(0) << std::endl;

       // index is outside range, throwing exception
       std::cout << "array.at(2) = " << array.at(2) << std::endl; 

       // never comes here
       std::cout << "array.at(1) = " << array.at(1) << std::endl;  
    }
    catch(const std::out_of_range& r)
    {
        std::cout << "Something goes wrong: " << r.what() << std::endl;
    }
    return 0;
}
array.at(0) = 1
Something goes wrong: array<>: index out of range
int pagesWordsLength = sizeof(pagesWords) / sizeof(pagesWords[0]);

realloc (pagesWords, sizeof(pagesWords[0]) * (pagesWordsLength + 1);

pagesWords[pagesWordsLength] = MY_NULL;

for (uint i = 0; i < 1000; i++)
{
  if (pagesWords[i] == MY_NULL)
  {
    break;
  }
}
#include <iostream>
using namespace std;
int main()
{
    int array[2];
    INT NOTHING;
    CHAR FOO[4];
    STRCPY(FOO, "BAR");
    array[0] = 1;
    array[1] = 2;
    array[3] = 3;
    array[4] = 4;
    cout << array[3] << endl;
    cout << array[4] << endl;
    COUT << FOO << ENDL;
    return 0;
}