malloc和calloc分配的内存块布局有什么区别?

10

calloc分配num块大小为size的内存:

void * calloc ( size_t num, size_t size );

在内存中为数组分配空间 为一个由num个元素组成且每个元素大小为size字节的数组分配一块内存,并将其所有位初始化为零。

相比之下,malloc只分配一块大小为size的内存:

void * malloc ( size_t size );

分配内存块 分配一块大小为size字节的内存块,返回指向该块开头的指针。


这两种方法之间除了calloc会对内存进行零初始化外还有其他区别吗?

calloc中的num块内存实际上是连续的,那么calloc中的num究竟是什么意思呢?

我认为这两种方法肯定有一些区别,否则定义两个不同的接口也就没有太多意义了?


是的,这就是为什么我甚至没有尝试思考内存是否非连续的原因。那么这是否意味着术语“n块内存”是误导性的? - Avantika Sk
@AvantikaSk 是的,那是误导。 - nos
1
实际上,calloc分配一个适合存储大小为n的元素数组的单个内存块。在大多数实现中,calloc调用malloc,然后将内存清零。我认为它们是意外有两个不同的原型,只是因为calloc将内存清零。 - Analog File
@moooeeeep:感谢您重新表达我的问题。 - Avantika Sk
1
可能是c difference between malloc and calloc的重复问题。 - Bo Persson
7个回答

4
抱歉,没有差异(但内存被清零了)。
当使用数组时,Calloc()非常有用,因为您手头上有两个不同的值:数组的大小和单个单元格的维数。在这两种情况下,返回的内存区域都是连续的,并且它们可能使用相同的数据结构来跟踪此类区域(但这取决于具体实现)。

如果我使用calloc(4,1),我能否在一个实例中为所有4个字节分配值? 例如:char *ptr = (char *)calloc(4,1); *ptr = <填充所有4个字节的某个值> 这样做可能吗?是否安全? - Avantika Sk
如果返回的指针不为空,那么它是否可能且安全:您可以保证分配的区域至少为4个字节。请记住:永远不要强制转换calloc/malloc(在C中)的返回值。 - Jack
此外:如果您想为分配的区域分配一个值,请不要使用calloc,因为它比malloc慢(由于初始化)。仅在确实需要零初始化时才使用calloc。 - Jack

2
在实践中,它们做的事情是一样的。 calloc 的优点在于良好的实现会在进行乘法以确定需要多少内存时执行溢出检测。
如果你像这样做:
void *
calloc(size_t nmemb, size_t size)
{
    size_t sz = nmemb * size;
    void *res = malloc(sz);

'sz'可能不会成为您期望的那样。malloc将分配比调用者预期的要少得多的空间,但调用者最终可能将返回的区域视为足够大。这会导致堆溢出,带有通常具有的所有安全影响。


1
我尝试了解 calloc 的工作原理。
我找到了下面的代码。
/* We use this function occasionally since the real implementation may
   be optimized when it can assume the memory it returns already is
   set to NUL.  */
void * weak_function
calloc (size_t nmemb, size_t size)
{   
  /* New memory from the trivial malloc above is always already cleared.
     (We make sure that's true in the rare occasion it might not be,
     by clearing memory in free, below.)  */
  size_t bytes = nmemb * size;

#define HALF_SIZE_T (((size_t) 1) << (8 * sizeof (size_t) / 2))
  if (__builtin_expect ((nmemb | size) >= HALF_SIZE_T, 0)
      && size != 0 && bytes / size != nmemb)
    return NULL;

  return malloc (bytes);
}

你可以看到calloc和malloc之间没有太大的区别。

你可以在这里浏览glibc的代码。

http://sourceware.org/git/?p=glibc.git;a=blob;f=elf/dl-minimal.c


0
你可以把calloc()看作是相当于:
void* calloc(size_t nmemb, size_t size)
{
  const size_t nbytes = nmemb * size;
  void *p = malloc(nbytes);
  if(p != NULL)
    memset(p, 0, nbytes);
  return p;
}

请注意,它可能会完全不同的实现方式,但它是上述内容的功能等效物。内存的“内部布局”没有区别,您将获得一个连续的块。

0

是的。 Calloc() 的作用是分配 n 个大小为 size_t size 的块,然后将每个大小为 size_t size 的块都初始化为零。


0

唯一真正的区别是使用 calloc() 进行 0 初始化。

为什么 calloc() 可以处理块大小和块计数,而 malloc() 则不行,对我来说一直不太清楚。


这个回答是什么意思?无论回答说什么,都已经在原帖中提到了。 - Alok Save
1
@Als回答了这个关于内存的问题:"除了calloc()的0初始化内存,它们有什么不同?"。他说:"唯一真正的区别就是calloc()的0初始化。",承认没有其他区别。 - glglgl

0

它们完全相同。Calloc要求您指定要分配多少个给定大小的块,因为它会将它们初始化为0。底层结构完全相同。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接