【问题标题】:How much memory does calloc actually allocate?calloc 实际分配了多少内存?
【发布时间】:2014-09-07 16:52:14
【问题描述】:

以下代码在测试时输出为

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

之后我尝试了这段代码,它连续运行而没有任何输出

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

【问题讨论】:

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

标签: c calloc


【解决方案1】:

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

当你向malloccalloc请求5个字节时,它不会转身向内核请求5个字节。那将需要永远。相反,libc 堆系统从内核中获取更大的内存块,并将其细分。

因此,当您请求少量内存时,通常在它之后还有大量可访问的内存尚未被 libc 分配,您可以访问它。当然,访问它是一个即时的错误秘诀。

只有在你恰好位于从内核获取的区域的最末端时,才会从末端引用获得 SIGnal。

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

【讨论】:

    【解决方案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 个字节时(即来自 calloc 的一个 sizeof(int),我有足够的空间容纳 16 个字节(即 4*sizeof(int)). This does not mean that I can freely write up to fourints after requesting memory for a singleint`,不过:写越界请求的内存仍然是未定义的行为。

    【讨论】:

      【解决方案3】:

      calloc 正在为给定 sn-p 中的3 int 分配内存。实际上,您正在访问未分配的内存。访问未分配的内存会调用未定义的行为

      【讨论】:

        【解决方案4】:

        calloc 仅分配您要求的内存量,在您的情况下为 3 个 int 变量

        但它不会在它创建的指针上创建一个边界(在你的情况下是 ptr)。所以你可以通过增加指针来访问未分配的内存。这正是你的情况..

        【讨论】:

          猜你喜欢
          • 2010-10-31
          • 2017-06-26
          • 1970-01-01
          • 2012-08-28
          • 1970-01-01
          • 2020-01-15
          • 2011-01-03
          • 2017-05-18
          相关资源
          最近更新 更多