我试图掌握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]);
}
令人惊讶的是,该代码编译并运行完美。怎么可能?
答案 0 :(得分:9)
C不强制任何数组边界检查,因此当您请求5个整数的空间时,您使用了更多。
事实上,你覆盖了4个真正没有为你的特定用途预留的内存位置。你的程序过去内存中为数组预留的区域,并开始将值存储在分配区域之外的内存中。
这个“有效”的事实只是纯粹的运气,而不是依赖于它。它可能会在接下来的100次中运行,或者可能会在您尝试下次下次时失败,很可能是“分段错误”消息。
防御性编程,就像你通过明智地检查malloc的返回值一样,注意你负责边界检查,编译启用了高警告级别的代码等等是你最好的防御措施防止这些错误。其他工具,如valgrind,lint类型的检查器也可以提供帮助,但最终还是取决于你。
C的最大优势之一,它自由地做各种各样的事情,低级和高级,也是IMO最大的弱点之一。如果Java是沃尔沃,那么C或许更像是法拉利,有时会出现不稳定的突破:)
答案 1 :(得分:0)
C不进行边界检查。
答案 2 :(得分:0)
那怎么可能?
你正在写完数组的末尾。这个doesn't cause the program to crash(立即),因为在C中没有边界检查,但是,如果写得足够远,它最终会导致错误。有时你可能会写出数百个int值,而有时你可能无法写任何额外的值。
答案 3 :(得分:0)
计算机中的内存基本上是按顺序排列的。你问malloc
给你一小段记忆 - 足够5个整数。计算机中可用的内存肯定比分配长度为5的数组要多。因此,如果您在arr[8]
处写入或读取,则会在内存中的其他位置写入。
通常,现代计算机有如此多的内存,你可能正在写一些没有使用的地方。但有时候,您会不小心覆盖其他一些malloc
数据。
请注意有时您的程序会崩溃(如您所料)。这是因为您可能尝试在分配的内存之外写入,该地址不再有效。您的操作系统通常会捕获并为您崩溃程序。