测试时的以下代码,输出为
1
0
0
2
0
这很神奇,因为ptr [3],ptr [4]没有任何内存分配。虽然它们存储了价值并打印出来。我在ptr [i]中尝试了相同的代码,它们再次成功编译并给出了结果,但对于非常大的值,大约为100000,程序崩溃了。如果calloc()在单个调用上分配如此大的内存,则它不值得有效。那么calloc()如何工作?这种差异在哪里?
#include <stdio.h>
void main() {
int * ptr = (int *)calloc(3,sizeof(int));//allocates memory to 3 integer
int i = 0;
*ptr = 1;
*(ptr+3) = 2;//although memory is not allocated but get initialized
for( i =0 ; i<5 ; ++i){
printf("%d\n",*ptr++);
}
}
之后我尝试了这个不带任何输出连续运行的代码
#include <stdio.h>
void main() {
int * ptr = (int *)calloc(3,sizeof(int));
int i = 0;
*ptr = 1;
*(ptr+3) = 2;
//free(ptr+2);
for( ; ptr!=NULL ;)
{
//printf("%d\n",*ptr++);
i++;
}
printf("%d",i);
}
答案 0 :(得分:2)
你混淆了两种内存分配:内核和libc。
当您向malloc
或calloc
询问5个字节时,它不会转向并向内核询问5个字节。这将永远 。相反,libc堆系统从内核获取更大的内存块,并对其进行细分。
因此,当你要求少量内存时,通常会有很多可访问的内存,它们尚未被libc分配,你可以访问它。当然,访问它是错误的即时配方。
如果您恰好位于从内核获取的区域的最后,那么唯一一次引用末尾将获得SIGnal的时间。
我建议您尝试在valgrind
下运行测试用例以获得更多信息。
答案 1 :(得分:2)
您拥有的代码具有未定义的行为。但是,您没有遇到崩溃,因为malloc
和calloc
确实经常分配的内存超出您的要求。
告诉你有多少记忆的一种方法是调用realloc
增加大小,直到你找回的指针与原始指针不同。虽然标准并不能保证这个技巧能够发挥作用,但通常会产生良好的效果。
以下是运行此实验的方法:
int *ptr = calloc(1,sizeof(int));
// Prevent expansion of the original block
int *block = calloc(1, sizeof(int));
int *tmp;
int k = 1;
do {
tmp = realloc(ptr, k*sizeof(int));
k++;
} while (tmp == ptr);
printf("%d\n", k-1);
这会在我的系统和ideone(demo on ideone)上打印4
。这意味着当我请求4个字节(即sizeof(int)
中的一个calloc
时,我有足够的空间容纳16个字节(即4 * sizeof(int)). This does not mean that I can freely write up to four
int s after requesting memory for a single
int但是,写过所请求内存的边界仍然是未定义的行为。
答案 2 :(得分:1)
calloc
正在为给定代码段中的3
int
分配内存。实际上你正在访问未分配的内存。访问未分配的内存会调用未定义的行为。
答案 3 :(得分:0)
calloc仅分配您提出的内存量,在您的情况下为3个int变量
但它不会在它创建的指针上创建一个绑定(在你的情况下是ptr)。所以你只需通过递增指针就可以访问未分配的内存。那就是你的情况下发生了什么......