calloc实际分配了多少内存?

calloc实际分配了多少内存?,c,calloc,C,Calloc,以下代码在测试时给出如下输出: 1 0 0 2 0 这是令人惊讶的,因为ptr[3],ptr[4]没有任何内存分配。尽管他们将价值存储在其中并打印出来。我在ptr[I]中的几个较大的I上尝试了相同的代码,再次编译成功并给出了结果,但对于非常大的I值,大约100000,程序崩溃。如果calloc()在一次调用中分配了如此大的内存,那么它就不值得有效使用。那么calloc()是如何工作的呢?这种差异在哪里 #include <stdio.h> void main() { int

以下代码在测试时给出如下输出:

1
0
0
2
0
这是令人惊讶的,因为ptr[3],ptr[4]没有任何内存分配。尽管他们将价值存储在其中并打印出来。我在ptr[I]中的几个较大的I上尝试了相同的代码,再次编译成功并给出了结果,但对于非常大的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++);
    }
}
#包括
void main(){
int*ptr=(int*)calloc(3,sizeof(int));//将内存分配给3个整数
int i=0;
*ptr=1;
*(ptr+3)=2;//虽然未分配内存,但已初始化

对于(i=0;i
calloc
正在为给定代码段中的
3
int
分配内存。实际上,您正在访问未分配内存。访问未分配内存将调用未定义的行为

calloc
正在为给定代码段中的
3
int
分配内存。实际您正在访问未分配的内存。访问未分配的内存调用未定义的行为

您混淆了两种内存分配:内核的和libc的

当您向
malloc
calloc
请求5个字节时,它不会掉头向内核请求5个字节。这将花费永远的时间。相反,libc堆系统从内核获取更大的内存块,并对其进行细分

因此,当你需要少量内存时,通常会有大量的更易访问的内存在它之后,而libc尚未分配这些内存,你可以访问它们。当然,访问它会立即导致bug

如果您恰好位于从内核获取的区域的最末端,那么从末端引用将获得信号的唯一时间


我建议您尝试在
valgrind
下运行测试用例,以获得更多的洞察力。

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

当您向
malloc
calloc
请求5个字节时,它不会掉头向内核请求5个字节。这将花费永远的时间。相反,libc堆系统从内核获取更大的内存块,并对其进行细分

因此,当你需要少量内存时,通常会有大量的更易访问的内存在它之后,而libc尚未分配这些内存,你可以访问它们。当然,访问它会立即导致bug

如果您恰好位于从内核获取的区域的最末端,那么从末端引用将获得信号的唯一时间


我建议您尝试在
valgrind
下运行测试用例以获得更多的洞察力。

您拥有的代码具有未定义的行为。但是,您不会发生崩溃,因为
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()上打印
4
。这意味着当我从
calloc
请求4个字节(即一个
sizeof(int)
)时,我有足够的空间容纳16个字节(即4*sizeof(int)
)。这并不意味着在为单个
int`请求内存后,我可以自由写入多达四个
int
s,但是:写入超过请求内存边界的内容仍然是未定义的行为。

您拥有的代码具有未定义的行为。但是,您不会因为
malloc
calloc
ind而崩溃eed通常分配的内存比您要求的要多

判断内存大小的一种方法是,随着大小的增加调用
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()上打印
4
。这意味着当我从
calloc
请求4个字节(即一个
sizeof(int)
)时,我有足够的空间容纳16个字节(即4*sizeof(int)
)。这并不意味着在为单个
int`请求内存后,我可以自由写入多达四个
int
s,但是:写入超过请求内存边界的内容仍然是未定义的行为。

calloc仅分配您请求的内存量,在您的情况下,这将用于3个int变量


但是它不会在它所创建的指针上创建一个绑定(在您的例子ptr中)。因此,您可以通过增加指针来访问未分配的内存。这正是在您的例子中发生的情况。

calloc只分配您所请求的内存量,在您的例子中,这将用于3个int变量


但是它不会在已经创建的指针上创建一个绑定(在您的例子中是ptr)。因此,您可以通过增加指针来访问未分配的内存。这正是您的情况所发生的。

访问进程不拥有的内存是未定义的。有时,它会崩溃。有时,它似乎可以工作。任何事情都可能发生。仅仅因为写入没有崩溃并不意味着
calloc
“已分配”内存。相反,您正在覆盖它没有分配给您的内存,并且可能用于其他目的。访问进程不拥有的内存是未定义的。有时,它会崩溃。有时,它似乎可以工作。任何事情都可能发生。仅仅因为写操作没有崩溃并不意味着