【问题标题】:malloc and callocmalloc 和 calloc
【发布时间】:2012-03-02 01:24:02
【问题描述】:

我知道这个问题可能被标记为 malloc 和 calloc 之间差异的重复,但我仍然想问它。

我知道 calloc 会初始化内存块,这里我的问题不在于那部分。

我的问题是

malloc 的定义是分配一块指定大小的内存。

calloc 表示它分配了多个内存块,每个内存块的大小相同。

这样分配一块内存和多块内存真的是两者的区别吗?

因为我觉得我们可以使用 malloc 做同样的事情,这可以通过 calloc 完成。

例如:

int *ptr;
ptr=(int *) malloc(100 * (sizeof(int)));

int *ptr;
ptr=(int *) calloc(100,sizeof(int));

最终会分配 100 倍于 int 所需的内存。

【问题讨论】:

    标签: c memory-management malloc calloc


    【解决方案1】:

    calloc 用零填充内存。

    p=calloc(n, m); 
    

    等价于

    p=malloc(n*m); 
    memset(p, 0, m * n);
    

    因此,如果您打算将分配的内存设置为零,那么使用malloc 您必须计算两次n*m,或者使用临时变量,这就是calloc 所做的。

    编辑:我刚刚阅读了ISO C标准,发现没有指定calloc的实现应该检查n*m是否溢出,即是否超过了C99标准中的常量SIZE_MAX .

    【讨论】:

    • 那么除了初始化为零之外,两者之间没有其他区别吗?
    • 正如我所说,在记忆方面它们是等价的。
    • 等效性不是 100%,原因有两个。首先,存在n*m 溢出的陷阱。如果产品太大,calloc 将失败,malloc 只需分配更少。其次,calloc 可能比malloc+memset 快(但比malloc 慢)。
    • 首先,同意。其次,我从来没有说过相反的话!
    • @urogen:我看不到 malloc(n) - 或任何分配器 - 如何分配 less 比'n'字节?如果它不能分配请求的数量,它应该只是失败
    【解决方案2】:

    您的代码示例是正确的...ptr 指向的实际内存大小将相同(即,100 个int 对象堆上的数组)。正如其他人所提到的,对calloc 的调用实际上会将内存清零,而malloc 只会给你一个指向该内存的指针,并且内存中可能有也可能没有全零。例如,如果您获得从另一个对象回收的内存,那么对 malloc 的调用仍将具有其先前使用的值。因此,如果您将内存视为“干净”的内存,并且不使用某些默认值对其进行初始化,那么您最终会在程序中出现某种类型的意外行为。

    【讨论】:

      【解决方案3】:

      是的,主要区别如上所述。 从操作系统内存分配的角度来看, calloc() 也比 malloc() 慢。

      malloc() 返回的指针在程序触及 malloc() 之前不会触及实际内存。而 calloc() 返回的是带有 RAM 的内存。

      【讨论】:

      • :你能详细说明第二部分吗
      • 我不认为第二部分是正确的,至少在任何现代受保护内存操作系统(如 Linux/Unix/Windows)上都不正确……你能进一步解释一下你的意思,以防万一我'我误解了什么?
      • 像 Linux 这样的操作系统遵循乐观的内存分配策略。因此 malloc 返回的指针在程序使用该内存之前不受物理内存的支持。从硬件的角度来看,它们是 2 个页面,即匿名页面和文件支持页面。当我们执行 malloc() 时,我们会得到匿名页面。匿名页面可以读取交换区域,对于 calloc(),操作系统还必须通过交换其他进程来找到合适的内存区域,这可能会使其变慢。
      • +1 感谢您的解释,尽管您可能希望更改第二段中的措辞,因为您的表述方式有点令人困惑……也许您应该明确提及“因为乐观的记忆操作系统级别的分配,...”等
      【解决方案4】:

      calloc 也将内存块初始化为包含零,这与 malloc 不同。

      【讨论】:

      • 是的,我知道,但我的问题不同
      • 两者还有其他区别吗?
      • @haris:嗯,你引用了主要区别,这里的答案引用了你错过的一个重要区别。所以除了这些没有其他区别。
      【解决方案5】:

      这个网站之前已经提到过,但是从其他答案来看,我认为值得重复;将两个整数相乘可能会导致溢出,如果发生这种情况,

      ptr = malloc(num*size);
      

      可能不会得到想要的结果(并且很可能会导致以后的分段错误)。对于这些情况,应该首选calloc(num,size)(尽管您也可以在调用malloc 之前测试溢出,如果calloc() 将新分配的内存初始化为零这一事实困扰您)。

      【讨论】:

        【解决方案6】:

        两者的主要区别是calloc将内存块初始化为零,而malloc创建的内存块包含垃圾值。

        所以更适合使用 calloc 代替 malloc 以避免代码中的不确定性。

        【讨论】:

          【解决方案7】:

          ===您可以看到 ma​​llac()calloc() 函数的以下区别===

          初始化:
          malloc() 不会清除和初始化分配的内存。
          calloc() 将分配的内存初始化为零。

          语法:

          void *malloc(size_t size);                   // syntex for malloc() function
          void *calloc(size_t num, size_t size);       // syntex for calloc() function
          
          // example
          ptr = malloc(num*size);   // for malloc() function
          ptr = calloc(num,size);   // for calloc() function
          

          论据:
          如果您考虑 malloc() 语法,它只需要 1 个参数。
          如果您考虑 calloc() 语法,它将采用 2 个参数。

          内存分配方式::
          malloc() 函数从可用堆中分配所需“大小”的内存。
          calloc() 函数分配的内存大小等于“num *size”。

          【讨论】:

            猜你喜欢
            • 2013-11-17
            • 2020-03-22
            • 2010-12-05
            • 2020-04-08
            • 2013-06-06
            • 2018-05-28
            • 2011-07-03
            • 2011-02-06
            相关资源
            最近更新 更多