7

我试图掌握 C 中的 malloc 函数,并编写了以下代码:

int i;

int *arr = (int*)malloc(5*sizeof(int)); 

if(arr==NULL){

  printf("Failed to allocate memory for arr...\n");
  exit(1);

}

我认为这意味着只能将 5 个元素添加到数组中。为了测试这是否属实,我添加了以下代码:

arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr[3] = 4;
arr[4] = 5;
arr[5] = 6;
arr[6] = 7;
arr[7] = 8;
arr[8] = 9;

for(i=0;i<9;i++){

    printf("%d\n",arr[i]);

}

令人惊讶的是,该代码编译并完美运行。这怎么可能?

4

4 回答 4

9

C 不强制执行任何数组边界检查,因此当您请求 5 个整数的空间时,您使用了更多。

事实上,您覆盖了 4 个内存位置,这些内存位置实际上并没有为您的特定目的留出。您的程序经过了为数组预留的内存区域,并开始将值存储在分配区域之外的内存中。

这个“有效”的事实只是纯粹的运气,而不是依赖的东西。它可能会在接下来的 100 次中工作,或者在您下次尝试时可能会失败,很可能会出现“分段错误”消息。

防御性编程,就像您通过明智地检查 malloc 的返回值所做的那样,注意负责边界检查,编译启用了高警告级别的代码等,是防止此类错误的最佳防御措施。其他工具,例如valgrind、lint 类型检查器也可以提供帮助,但最终取决于您。

C 的最大优势之一,它可以自由地做各种事情,无论是低级还是高级,这也是其最大的弱点之一。如果 Java 是一辆沃尔沃,那么 C 可能更像是一辆有时断断续续的法拉利 :)

于 2012-07-18T22:48:49.413 回答
0

C 不做边界检查。

于 2012-07-18T22:49:31.730 回答
0

这怎么可能?

您正在写超出数组的末尾。这不会导致程序(立即)崩溃,因为在 C 中没有边界检查,但是,如果你写得足够远,它最终会导致错误。有时您可能能够编写数百个 int 值,而有时您可能无法编写任何额外的值。

于 2012-07-18T22:49:40.737 回答
0

您计算机中的内存基本上是按顺序排列的。你要求malloc给你一小块内存——足够 5 个整数。您的计算机中的可用内存肯定比分配长度为 5 的数组所需的内存多。因此,如果您写入或读取arr[8],您正在写入内存中的其他位置。

通常,现代计算机具有如此多的内存,以至于您可能正在编写未使用的某个地方。但偶尔,您会不小心覆盖其他一些malloc'd 数据。

请注意,有时您的程序会崩溃(如您所料)。这是因为您可能会尝试在分配的内存之外写这么远,以至于地址不再有效。您的操作系统通常会捕捉到这一点并为您崩溃您的程序。

于 2012-07-18T22:52:43.517 回答