C/C++ 避免数组越界的方法

2020-06-20 17:59:46王冬梅

运行结果为:

a[MAX]:
a[0]=1 a[1]=2 a[2]=3 a[3]=4 a[4]=5 a[5]=6 a[6]=7 a[7]=8 a[8]=9 a[9]=10
b[MAX1]:
b[0]=1 b[1]=2 b[2]=3 b[3]=4 b[4]=5 b[5]=0 b[6]=0 b[7]=0 b[8]=0 b[9]=0 b[10]=6 b[11]=7 b[12]=8 b[13]=9 b[14]=10
c[MAX2]:
c[0]=1 c[1]=6 c[2]=7 c[3]=8 c[4]=9 c[5]=10

对数组做越界检查,确保索引值位于合法的范围之内

要避免数组越界,除了上面所阐述的显式指定数组的边界之外,还可以在数组使用之前进行越界检查,检查数组的界限和字符串(也以数组的方式存放)的结束,以保证数组索引值位于合法的范围之内。例如,在写处理数组的函数时,一般应该有一个范围参数;在处理字符串时总检查是否遇到空字符‘'。

来看下面一段代码示例:

#define ARRAY_NUM 10
int *TestArray(int num,int value)
{
  int *arr=NULL;
  arr=(int *)malloc(sizeof(int)*ARRAY_NUM);
  if(arr!=NULL)
  {
    arr[num]=value;
  }
  else
  {
    /*处理arr==NULL*/
  }
  return arr;
}

从上面的“int*TestArray(int num,int value)”函数中不难看出,其中存在着一个很明显的问题,那就是无法保证 num 参数是否越界(即当 num>=ARRAY_NUM 的情况)。因此,应该对 num 参数进行越界检查,示例代码如下所示:

int *TestArray(int num,int value)
{
  int *arr=NULL;
  /*越界检查(越上界)*/
  if(num<ARRAY_NUM)
  {
    arr=(int *)malloc(sizeof(int)*ARRAY_NUM);
    if(arr!=NULL)
    {
      arr[num]=value;
    }
    else
    {
      /*处理arr==NULL*/
    }
  }
  return arr;
}

这样通过“if(num<ARRAY_NUM)”语句进行越界检查,从而保证 num 参数没有越过这个数组的上界。现在看起来,TestArray() 函数应该没什么问题,也不会发生什么越界错误。

但是,如果仔细检查,TestArray() 函数仍然还存在一个致命的问题,那就是没有检查数组的下界。由于这里的 num 参数类型是 int 类型,因此可能为负数。如果 num 参数所传递的值为负数,将导致在 arr 所引用的内存边界之外进行写入。

当然,你可以通过向“if(num<ARRAY_NUM)”语句里面再加一个条件进行测试,如下面的代码所示:

 if(num>=0&&num<ARRAY_NUM)
 {
 }

但是,这样的函数形式对调用者来说是不友好的(由于 int 类型的原因,对调用者来说仍然可以传递负数,至于在函数中怎么处理那是另外一件事情),因此,最佳的解决方案是将 num 参数声明为 size_t 类型,从根本上防止它传递负数,示例代码如下所示:

int *TestArray(size_t num,int value)
{
  int *arr=NULL;
  /*越界检查(越上界)*/
  if(num<ARRAY_NUM)
  {
    arr=(int *)malloc(sizeof(int)*ARRAY_NUM);
    if(arr!=NULL)
    {
      arr[num]=value;
    }
    else
    {
      /*处理arr==NULL*/
    }
  }
  return arr;
}