calloc实际分配了多少内存?

时间:2014-09-07 16:52:15

标签: c calloc

测试时的以下代码,输出为

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);
}

4 个答案:

答案 0 :(得分:2)

你混淆了两种内存分配:内核和libc。

当您向malloccalloc询问5个字节时,它不会转向并向内核询问5个字节。这将永远 。相反,libc堆系统从内核获取更大的内存块,并对其进行细分。

因此,当你要求少量内存时,通常会有很多可访问的内存,它们尚未被libc分配,你可以访问它。当然,访问它是错误的即时配方。

如果您恰好位于从内核获取的区域的最后,那么唯一一次引用末尾将获得SIGnal的时间。

我建议您尝试在valgrind下运行测试用例以获得更多信息。

答案 1 :(得分:2)

您拥有的代码具有未定义的行为。但是,您没有遇到崩溃,因为malloccalloc确实经常分配的内存超出您的要求。

告诉你有多少记忆的一种方法是调用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)。所以你只需通过递增指针就可以访问未分配的内存。那就是你的情况下发生了什么......