C – malloc和数组混淆

我试图掌握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]); } 

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

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

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

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

防御性编程,就像你通过明智地检查malloc的返回值,注意负责边界检查,编译启用了高警告级别的代码等等,是防御这些错误的一些最好的防御。 其他工具,如valgrind ,lint类型的检查器也可以提供帮助,但最终还是取决于你。

C的最大优势之一,它自由地做各种各样的事情,低级和高级,也是IMO最大的弱点之一。 如果Java是沃尔沃,那么C或许更像是法拉利,有时候会有多乱的突破:)

怎么可能?

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

计算机中的内存基本上是按顺序排列的。 你让malloc给你一小段记忆 – 足够5个整数。 你的计算机中可用的内存肯定比分配长度为5的数组要多。因此,如果你写入或读取arr[8] ,你就会在内存中写入其他内容。

通常,现代计算机具有如此多的内存,您可能正在写一些未使用的内容。 但有时候,你会不小心覆盖其他一些malloc数据。

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

C不进行边界检查。