931

What is the difference between doing:

ptr = malloc(MAXELEMS * sizeof(char *));

And:

ptr = calloc(MAXELEMS, sizeof(char*));

When is it a good idea to use calloc over malloc or vice versa?

Ninjakannon
  • 3,751
  • 7
  • 53
  • 76
user105033
  • 18,800
  • 19
  • 58
  • 69
  • 48
    [In C you don't cast the result of `malloc` family](http://stackoverflow.com/q/605845/995714) – phuclv Feb 17 '16 at 07:55
  • 9
    In C, you could write the above more generically as: `ptr = calloc(MAXELEMS, sizeof(*ptr));` – chqrlie Oct 26 '16 at 07:19
  • 8
    An interesting post about the difference between calloc and malloc+memset https://vorpus.org/blog/why-does-calloc-exist/ – ddddavidee Dec 13 '16 at 16:06
  • 2
    @ddddavidee I too found that blog after I was dissatisfied with so many answers on the net. Nathaniel J. Smith deserves 100+ SO points for his analysis. – lifebalance Apr 10 '18 at 14:59
  • Related: [Can calloc() allocate more than SIZE_MAX in total?](https://stackoverflow.com/q/52699574) – MCCCS Oct 10 '18 at 11:07

14 Answers14

994

calloc() gives you a zero-initialized buffer, while malloc() leaves the memory uninitialized.

For large allocations, most calloc implementations under mainstream OSes will get known-zeroed pages from the OS (e.g. via POSIX mmap(MAP_ANONYMOUS) or Windows VirtualAlloc) so it doesn't need to write them in user-space. This is how normal malloc gets more pages from the OS as well; calloc just takes advantage of the OS's guarantee.

This means calloc memory can still be "clean" and lazily-allocated, and copy-on-write mapped to a system-wide shared physical page of zeros. (Assuming a system with virtual memory.) The effects are visible with performance experiments on Linux, for example.

Some compilers even can optimize malloc + memset(0) into calloc for you, but it's best to just use calloc in the source if you want zeroed memory. (Or if you were trying to pre-fault it to avoid page faults later, that optimization will defeat your attempt.)

If you aren't going to ever read memory before writing it, use malloc so it can (potentially) give you dirty memory from its internal free list instead of getting new pages from the OS. (Or instead of zeroing a block of memory on the free list for a small allocation).


Embedded implementations of calloc may leave it up to calloc itself to zero memory if there's no OS, or it's not a fancy multi-user OS that zeros pages to stop information leaks between processes.

On embedded Linux, malloc could mmap(MAP_UNINITIALIZED|MAP_ANONYMOUS), which is only enabled for some embedded kernels because it's insecure on a multi-user system.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Fred Larson
  • 60,987
  • 18
  • 112
  • 174
  • 260
    The *alloc variants are pretty mnemonic - clear-alloc, memory-alloc, re-alloc. – Cascabel Oct 08 '09 at 15:07
  • 52
    Use malloc() if you are going to set everything that you use in the allocated space. Use calloc() if you're going to leave parts of the data uninitialized - and it would be beneficial to have the unset parts zeroed. – Jonathan Leffler Oct 08 '09 at 15:16
  • 284
    `calloc` is not necessarily more expensive, since OS can do some tricks to speed it up. I know that FreeBSD, when it gets any idle CPU time, uses that to run a simple process that just goes around and zeroes out deallocated blocks of memory, and marks blocks thus processes with a flag. So when you do `calloc`, it first tries to find one of such pre-zeroed blocks and just give it to you - and most likely it will find one. – Pavel Minaev Oct 08 '09 at 15:18
  • 3
    Using calloc() is probably a safer bet in general, unless you're trying to optimize every last tiny bit out of your code (and even then, as others have pointed out, your efforts may be futile). – Andrew Song Oct 08 '09 at 15:32
  • 32
    I tend to feel that if your code becomes "safer" as a result of zero-initing allocations by default, then your code is insufficiently safe whether you use malloc or calloc. Using malloc is a good indicator that the data needs initialisation - I only use calloc in cases where those 0 bytes are actually meaningful. Also note that calloc doesn't necessarily do what you think for non-char types. Nobody really uses trap representations any more, or non-IEEE floats, but that's no excuse for thinking your code is truly portable when it isn't. – Steve Jessop Oct 08 '09 at 15:51
  • 4
    "Safer" is probably an overstatement, it's more like "more likely to crash rather than silently corrupt data" - which is still relevant to code security (as a last barrier of defense), and it definitely makes it easier to debug crashes. That said, very good point about `float` (and other types for which all-bits-0 may not mean what you think they mean). – Pavel Minaev Oct 08 '09 at 19:25
  • 1
    @Pavel: `char *foo = malloc(foolen); assert(foo && memset(foo,0,foolen));` covers the debugging aspect, or you could use an eye-catcher byte other than 0. From a last-line of security POV, maybe it would be better to link against a version of malloc which clears the bytes (or sets them to an eye-catcher pointer-sized value, which is mapped to be non-readable and non-writeable), rather than have a policy to call calloc instead? – Steve Jessop Oct 12 '09 at 15:30
  • @Steve: I like that idea. I'm thinking of writing a simple debugging-oriented `malloc` sometime using `mmap` for each allocation with a guard page right after the last allocated byte, and I might incorporate your idea for filling memory with a special crash-inducing pointer value too. – R.. GitHub STOP HELPING ICE Jan 05 '11 at 16:02
  • 1
    @Jefromi just wanted to complain about "A Book on C", which describes calloc as "Allocates contiguous space". "c" for "contiguous", huh? Bizarre. "Clear" makes sense. Kernighan thinks it means clear, too http://www.quora.com/C-programming-language/What-does-the-c-stand-for-in-calloc – 13ren May 16 '13 at 13:30
  • and some early source of calloc comments `calloc - allocate and clear memory block` http://minnie.tuhs.org/cgi-bin/utree.pl?file=V7M/src/libc/gen/calloc.c From JimBalter's comment here http://stackoverflow.com/a/12555996/50979 – 13ren May 16 '13 at 13:35
  • 23
    @SteveJessop "Safer" isn't the correct word. I think "Deterministic" is the better term. Code that is more deterministic rather than having failures that are dependent on timing and data sequences, will be easier to isolate failures. Calloc is sometimes an easy way to get that determinism, versus explicit initialization. – dennis May 04 '14 at 13:57
  • 2
    @dennis, the point people are making is that if your code's behaviour or even execution path depends on the contents of uninitialized memory, that's usually a problem right there. There are some cases where you can prove that it's ok to do it, like http://research.swtch.com/sparse, but that's very much the exception. – Peter Cordes Dec 07 '14 at 16:22
  • 1
    @dennis, totally agree. I think its definitely better to prefer deterministic code over non deterministic code. Pavel made similar point. If you have a bug which unintentionally reads non-initialized memory, would you prefer its read random data, or null data? – Darren Smith Dec 16 '14 at 19:11
  • 4
    Just to add: calloc adds another defensive measure: it is usually save against integer overflow, for example in glibc they check that size multiplied by number of elements does not wrap over maximum of size_t limit. Usually you don't check for overflow when you call malloc and multiply size of an element by number of elements, but calloc does it for you and fails the call if it does overflow; (actually this is something that can be exploited if you infer these values from message that you have just read over the net). – MichaelMoser Jun 25 '15 at 07:32
  • 1
    @PavelMinaev About that FreeBSD process that goes around zeroing memory. Do you have any references on it? I find this idea very interesting... – Enzo Ferber Sep 16 '15 at 01:46
  • I wrote a [contrived scenario](http://pastebin.com/raw.php?i=YuvxrC2d) about malloc and security. If malloc's not zeroing memory, then I take it the kernel is. – Braden Best Oct 15 '15 at 19:13
  • 1
    @B1KMusic: On your OS, with your compiler, with that version of the compiler, with the compile options you specified, that may be the case. Don't count on it for anything important. – Fred Larson Oct 15 '15 at 19:58
  • 2
    You might add a note about this: *although most modern platforms represent the null pointer as all bits zero, the C Standard does not guarantee that the elements of the array allocated by `calloc()` can be safely assumed to be initialized to the `NULL` pointer.* – chqrlie Oct 26 '16 at 07:23
  • Is it correct to say the memory allocated both in case off `calloc` and `malloc` are contiguous in nature. I read [here](https://www.programiz.com/c-programming/c-dynamic-memory-allocation) that - `The only difference between malloc() and calloc() is that, malloc() allocates single block of memory whereas calloc() allocates multiple blocks of memory each of same size and sets all bytes to zero.` I believe this is incorrect. Isn't it? I believe `calloc` got its name from `clear allocated memory` i.e. zero-out the allocated memory which is the only difference when I compare it to `malloc`. – RBT Feb 09 '17 at 02:45
  • I could certainly imagine an alloc followed by a loop to 0000 0000 all the bytes. Where I wanted that result, calloc alone seems better. – alan2here Sep 09 '17 at 19:12
  • 1
    @Nik-Lz That was answered in a comment by ddddavidee on the original question. Turns out calloc can be much faster (100x). The article was a really good read. There was another big difference in there too--Passing 2 operands lets calloc error-check large allocations where malloc would just overflow and return a buffer with less memory than you asked for. – Bill K Mar 19 '18 at 23:12
394

A less known difference is that in operating systems with optimistic memory allocation, like Linux, the pointer returned by malloc isn't backed by real memory until the program actually touches it.

calloc does indeed touch the memory (it writes zeroes on it) and thus you'll be sure the OS is backing the allocation with actual RAM (or swap). This is also why it is slower than malloc (not only does it have to zero it, the OS must also find a suitable memory area by possibly swapping out other processes)

See for instance this SO question for further discussion about the behavior of malloc

Community
  • 1
  • 1
Isak Savo
  • 34,957
  • 11
  • 60
  • 92
  • 58
    `calloc` need not write zeros. If the allocated block consists mostly of new zero pages provided by the operating system, it can leave those untouched. This of course requires `calloc` to be tuned to the operating system rather than a generic library function on top of `malloc`. Or, an implementor could make `calloc` compare each word against zero before zeroing it. This would not save any time, but it would avoid dirtying the new pages. – R.. GitHub STOP HELPING ICE Jan 04 '11 at 13:46
  • 3
    @R.. interesting note. But in practice, does such implementations exist in the wild? – Isak Savo Jan 04 '11 at 14:00
  • 12
    All `dlmalloc`-like implementations skip the `memset` if the chunk was obtained via `mmap`ing new anonymous pages (or equivalent). Usually this kind of allocation is used for larger chunks, starting at 256k or so. I don't know of any implementations that do the comparison against zero before writing zero aside from my own. – R.. GitHub STOP HELPING ICE Jan 05 '11 at 15:57
  • 1
    `omalloc` also skips the `memset`; `calloc` does not need to touch any pages that are not already used by the application (page cache), ever. Though, [extremely primitive `calloc` implementations](http://stackoverflow.com/a/4319790/2171120) differ. – mirabilos Mar 31 '14 at 21:05
  • 10
    glibc's calloc checks if it's getting fresh memory from the OS. If so, it knows it DOESN'T need to write it, because mmap(..., MAP_ANONYMOUS) returns memory that's already zeroed. – Peter Cordes Dec 07 '14 at 22:45
  • On Windows `VirtualAlloc` also allocates pre-zeroed memory. – Joe Mar 02 '15 at 12:29
  • also that depends if the allocation spans several virtual memory pages or not; if it fits the current page then most often there is an arena header that is before the returned memory and which has to be modified, thereby turning the page into dirty state. (linked question talks about a really big allocation that spans many pages) – MichaelMoser Jun 27 '15 at 19:40
125

One often-overlooked advantage of calloc is that (conformant implementations of) it will help protect you against integer overflow vulnerabilities. Compare:

size_t count = get_int32(file);
struct foo *bar = malloc(count * sizeof *bar);

vs.

size_t count = get_int32(file);
struct foo *bar = calloc(count, sizeof *bar);

The former could result in a tiny allocation and subsequent buffer overflows, if count is greater than SIZE_MAX/sizeof *bar. The latter will automatically fail in this case since an object that large cannot be created.

Of course you may have to be on the lookout for non-conformant implementations which simply ignore the possibility of overflow... If this is a concern on platforms you target, you'll have to do a manual test for overflow anyway.

Daren Thomas
  • 67,947
  • 40
  • 154
  • 200
R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • 23
    Apparently the arithmetic overflow was what caused OpenSSH hole in 2002. Good article from OpenBSD on the perils of this with memory-related functions: http://undeadly.org/cgi?action=article&sid=20060330071917 – Philip P. Apr 24 '14 at 14:35
  • 5
    @KomradeP.: Interesting. Sadly the article you linked has misinformation right at the beginning. The example with `char` is **not** an overflow but rather an implementation-defined conversion when assigning the result back into a `char` object. – R.. GitHub STOP HELPING ICE Apr 24 '14 at 15:32
  • It's there probably for illustration purpose only. Because compiler is likely to optimise that away anyway. Mine compiles into this asm: push 1. – Philip P. Apr 24 '14 at 17:22
  • You should notice somewhere in that response that you assume a 32 bit `size_t` because I don't see a problem when `size_t` is 64 bits wide. – Patrick Schlüter Sep 20 '14 at 07:44
  • 1
    @tristopia: The point is not that the code is exploitable on all implementations, but that it's incorrect without additional assumptions and thus not correct/portable usage. – R.. GitHub STOP HELPING ICE Sep 20 '14 at 21:38
  • The thing is that some people (me) program exclusively on 64 bits machines. I had to scratch my head really long to even see where the overflow risk was. Had there been a mention of the size of `size_t` it would have been obvious. Granted, it's my problem that I develop now only on 64 bit machines, but ones obviousness is not necessarily the same as others (for instance I'm really good at finding `int` overflows in code from people with a 32 bits mental model). – Patrick Schlüter Sep 20 '14 at 22:59
  • 3
    @tristopia: If your mode of thinking is "`size_t` is 64-bit so that's no problem", that's a flawed way of thinking that's going to lead to security bugs. `size_t` is an abstract type that represents sizes, and there's no reason to think the arbitrary product of a 32-bit number and a `size_t` (note: `sizeof *bar` could in principle be greater than 2^32 on a 64-bit C implementation!) fits in `size_t`. – R.. GitHub STOP HELPING ICE Sep 20 '14 at 23:40
  • @PatrickSchlüter You not only will have a problem with 32-Bit `size_t`, if `size_t` is 16 Bit (or any value between) you would also have a problem (which is common on embedded Microcontrollers which often have less than 64KiB total space). – 12431234123412341234123 Jul 26 '17 at 13:43
  • See this link for more info :https://wiki.sei.cmu.edu/confluence/display/c/MEM07-C.+Ensure+that+the+arguments+to+calloc%28%29%2C+when+multiplied%2C+do+not+wrap – Krishna Kanth Yenumula Nov 13 '20 at 04:43
  • Relying on calloc to check that _will_ bite you, since non-conforming implementations are too common. https://github.com/gcc-mirror/gcc/blob/master/libiberty/calloc.c – Hans Olsson Dec 19 '22 at 16:10
  • @HansOlsson: libiberty is not an implementation present on any system. It's an internal component of some ancient GNU software optionally used when it thinks something is wrong with the host environment. If that code is actually getting used, though, it should be reported as a bug in GCC or whatever is using it. I am not aware of any remaining actual implementations (as part of the normal host system, not some application-shipped replacement, which you would not encounted writing your own code unless you made the broken replacement yourself) with this problem in the wild. – R.. GitHub STOP HELPING ICE Dec 19 '22 at 17:22
43

The documentation makes the calloc look like malloc, which just does zero-initialize the memory; this is not the primary difference! The idea of calloc is to abstract copy-on-write semantics for memory allocation. When you allocate memory with calloc it all maps to same physical page which is initialized to zero. When any of the pages of the allocated memory is written into a physical page is allocated. This is often used to make HUGE hash tables, for example since the parts of hash which are empty aren't backed by any extra memory (pages); they happily point to the single zero-initialized page, which can be even shared between processes.

Any write to virtual address is mapped to a page, if that page is the zero-page, another physical page is allocated, the zero page is copied there and the control flow is returned to the client process. This works same way memory mapped files, virtual memory, etc. work.. it uses paging.

Here is one optimization story about the topic: http://blogs.fau.de/hager/2007/05/08/benchmarking-fun-with-calloc-and-zero-pages/

Vishnu CS
  • 748
  • 1
  • 10
  • 24
t0rakka
  • 904
  • 9
  • 10
27

There's no difference in the size of the memory block allocated. calloc just fills the memory block with physical all-zero-bits pattern. In practice it is often assumed that the objects located in the memory block allocated with calloc have initilial value as if they were initialized with literal 0, i.e. integers should have value of 0, floating-point variables - value of 0.0, pointers - the appropriate null-pointer value, and so on.

From the pedantic point of view though, calloc (as well as memset(..., 0, ...)) is only guaranteed to properly initialize (with zeroes) objects of type unsigned char. Everything else is not guaranteed to be properly initialized and may contain so called trap representation, which causes undefined behavior. In other words, for any type other than unsigned char the aforementioned all-zero-bits patterm might represent an illegal value, trap representation.

Later, in one of the Technical Corrigenda to C99 standard, the behavior was defined for all integer types (which makes sense). I.e. formally, in the current C language you can initialize only integer types with calloc (and memset(..., 0, ...)). Using it to initialize anything else in general case leads to undefined behavior, from the point of view of C language.

In practice, calloc works, as we all know :), but whether you'd want to use it (considering the above) is up to you. I personally prefer to avoid it completely, use malloc instead and perform my own initialization.

Finally, another important detail is that calloc is required to calculate the final block size internally, by multiplying element size by number of elements. While doing that, calloc must watch for possible arithmetic overflow. It will result in unsuccessful allocation (null pointer) if the requested block size cannot be correctly calculated. Meanwhile, your malloc version makes no attempt to watch for overflow. It will allocate some "unpredictable" amount of memory in case overflow happens.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • Per the "another important detail" paragraph: that seems make to `memset(p, v, n * sizeof type);` a problem because `n * sizeof type` may overflow. Guess I'll need to use a `for(i=0;i – chux - Reinstate Monica Feb 14 '15 at 13:18
  • It would be helpful if there were a standard means by which code could assert that an implementation must use all-bits-zero as a null pointer (refusing compilation otherwise), since there exist implementations that use other null-pointer representations, but they are comparatively rare; code that doesn't have to run on such implementations can be faster if it can use calloc() or memset to initialize arrays of pointers. – supercat Aug 13 '16 at 21:03
  • @chux No, if an array with `n` elements exist where a element have the size `sizeof type`, then `n*sizeof type` can not overflow, because the maximum size of any object must be less than `SIZE_MAX`. – 12431234123412341234123 Jul 26 '17 at 13:49
  • @12431234123412341234123 True about an _array_ size <= `SIZE_MAX`, yet there are no _arrays_ here. The pointer returned from `calloc()` can point to allocated memory than exceeds `SIZE_MAX`. Many implementations do limit the product of the 2 args to `calloc()` to `SIZE_MAX`, yet the C spec does not impose that limit. – chux - Reinstate Monica Jul 26 '17 at 14:01
  • @AnT, are "Arithmetic overflow" and "Heap overflow" one and same thing? – Sandrious Aug 09 '23 at 12:24
22

from an article Benchmarking fun with calloc() and zero pages on Georg Hager's Blog

When allocating memory using calloc(), the amount of memory requested is not allocated right away. Instead, all pages that belong to the memory block are connected to a single page containing all zeroes by some MMU magic (links below). If such pages are only read (which was true for arrays b, c and d in the original version of the benchmark), the data is provided from the single zero page, which – of course – fits into cache. So much for memory-bound loop kernels. If a page gets written to (no matter how), a fault occurs, the “real” page is mapped and the zero page is copied to memory. This is called copy-on-write, a well-known optimization approach (that I even have taught multiple times in my C++ lectures). After that, the zero-read trick does not work any more for that page and this is why performance was so much lower after inserting the – supposedly redundant – init loop.

aashoo
  • 404
  • 4
  • 13
18

Number of blocks:
malloc() assigns single block of requested memory,
calloc() assigns multiple blocks of the requested memory

Initialization:
malloc() - doesn't clear and initialize the allocated memory.
calloc() - initializes the allocated memory by zero.

Speed:
malloc() is fast.
calloc() is slower than malloc().

Arguments & Syntax:
malloc() takes 1 argument:

  1. bytes

    • The number of bytes to be allocated

calloc() takes 2 arguments:

  1. length

    • the number of blocks of memory to be allocated
  2. bytes

    • the number of bytes to be allocated at each block of memory
void *malloc(size_t bytes);         
void *calloc(size_t length, size_t bytes);      

Manner of memory Allocation:
The malloc function assigns memory of the desired 'size' from the available heap.
The calloc function assigns memory that is the size of what’s equal to ‘num *size’.

Meaning on name:
The name malloc means "memory allocation".
The name calloc means "contiguous allocation".

Vishnu CS
  • 748
  • 1
  • 10
  • 24
Majbah Habib
  • 8,058
  • 3
  • 36
  • 38
14

calloc is generally malloc+memset to 0

It is generally slightly better to use malloc+memset explicitly, especially when you are doing something like:

ptr=malloc(sizeof(Item));
memset(ptr, 0, sizeof(Item));

That is better because sizeof(Item) is know to the compiler at compile time and the compiler will in most cases replace it with the best possible instructions to zero memory. On the other hand if memset is happening in calloc, the parameter size of the allocation is not compiled in in the calloc code and real memset is often called, which would typically contain code to do byte-by-byte fill up until long boundary, than cycle to fill up memory in sizeof(long) chunks and finally byte-by-byte fill up of the remaining space. Even if the allocator is smart enough to call some aligned_memset it will still be a generic loop.

One notable exception would be when you are doing malloc/calloc of a very large chunk of memory (some power_of_two kilobytes) in which case allocation may be done directly from kernel. As OS kernels will typically zero out all memory they give away for security reasons, smart enough calloc might just return it withoud additional zeroing. Again - if you are just allocating something you know is small, you may be better off with malloc+memset performance-wise.

AGS
  • 14,288
  • 5
  • 52
  • 67
virco
  • 257
  • 2
  • 4
  • 1
    +1 for the reminder that a generic implementation of a functionality in a system library is not necessarily faster than the same operation in the user code. – Patrick Schlüter Sep 20 '14 at 07:30
  • 1
    There is also a second point that make `calloc()` slower than `malloc()`: the multiplication for the size. `calloc()` is required to use a generic multiplication (if `size_t` is 64 bits even the very costly 64 bits*64 bits=64 bits operation) while the malloc() will often have a compile time constant. – Patrick Schlüter Sep 20 '14 at 07:37
  • 5
    glibc calloc has some smarts to decide how to most efficiently clear the returned chunk, e.g. sometimes only part of it needs clearing, and also an unrolled clear up to 9*sizeof(size_t). Memory is memory, clearing it 3 bytes at a time isn't going to be faster just because you're then going to use it to hold `struct foo { char a,b,c; };`. `calloc` is always better than `malloc`+`memset`, if you're always going to clear the whole `malloc`ed region. `calloc` has a careful but efficient check for int overflow in size * elements, too. – Peter Cordes Dec 07 '14 at 22:58
10

There are two differences.
First, is in the number of arguments. malloc() takes a single argument (memory required in bytes), while calloc() needs two arguments.
Secondly, malloc() does not initialize the memory allocated, while calloc() initializes the allocated memory to ZERO.

  • calloc() allocates a memory area, the length will be the product of its parameters. calloc fills the memory with ZERO's and returns a pointer to first byte. If it fails to locate enough space it returns a NULL pointer.

Syntax: ptr_var = calloc(no_of_blocks, size_of_each_block); i.e. ptr_var = calloc(n, s);

  • malloc() allocates a single block of memory of REQUSTED SIZE and returns a pointer to first byte. If it fails to locate requsted amount of memory it returns a null pointer.

Syntax: ptr_var = malloc(Size_in_bytes); The malloc() function take one argument, which is the number of bytes to allocate, while the calloc() function takes two arguments, one being the number of elements, and the other being the number of bytes to allocate for each of those elements. Also, calloc() initializes the allocated space to zeroes, while malloc() does not.

sigjuice
  • 28,661
  • 12
  • 68
  • 93
Jainendra
  • 24,713
  • 30
  • 122
  • 169
9

Difference 1:

malloc() usually allocates the memory block and it is initialized memory segment.

calloc() allocates the memory block and initialize all the memory block to 0.

Difference 2:

If you consider malloc() syntax, it will take only 1 argument. Consider the following example below:

data_type ptr = (cast_type *)malloc( sizeof(data_type)*no_of_blocks );

Ex: If you want to allocate 10 block of memory for int type,

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

If you consider calloc() syntax, it will take 2 arguments. Consider the following example below:

data_type ptr = (cast_type *)calloc(no_of_blocks, (sizeof(data_type)));

Ex: if you want to allocate 10 blocks of memory for int type and Initialize all that to ZERO,

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

Similarity:

Both malloc() and calloc() will return void* by default if they are not type casted .!

Felipe Augusto
  • 7,733
  • 10
  • 39
  • 73
Shivaraj Bhat
  • 841
  • 2
  • 9
  • 20
7

The calloc() function that is declared in the <stdlib.h> header offers a couple of advantages over the malloc() function.

  1. It allocates memory as a number of elements of a given size, and
  2. It initializes the memory that is allocated so that all bits are zero.
Vipin Diwakar
  • 115
  • 1
  • 3
7

malloc() and calloc() are functions from the C standard library that allow dynamic memory allocation, meaning that they both allow memory allocation during runtime.

Their prototypes are as follows:

void *malloc( size_t n);
void *calloc( size_t n, size_t t)

There are mainly two differences between the two:

  • Behavior: malloc() allocates a memory block, without initializing it, and reading the contents from this block will result in garbage values. calloc(), on the other hand, allocates a memory block and initializes it to zeros, and obviously reading the content of this block will result in zeros.

  • Syntax: malloc() takes 1 argument (the size to be allocated), and calloc() takes two arguments (number of blocks to be allocated and size of each block).

The return value from both is a pointer to the allocated block of memory, if successful. Otherwise, NULL will be returned indicating the memory allocation failure.

Example:

int *arr;

// allocate memory for 10 integers with garbage values
arr = (int *)malloc(10 * sizeof(int)); 

// allocate memory for 10 integers and sets all of them to 0
arr = (int *)calloc(10, sizeof(int));

The same functionality as calloc() can be achieved using malloc() and memset():

// allocate memory for 10 integers with garbage values   
arr= (int *)malloc(10 * sizeof(int));
// set all of them to 0
memset(arr, 0, 10 * sizeof(int)); 

Note that malloc() is preferably used over calloc() since it's faster. If zero-initializing the values is wanted, use calloc() instead.

elmiomar
  • 1,747
  • 2
  • 17
  • 27
6

A difference not yet mentioned: size limit

void *malloc(size_t size) can only allocate up to SIZE_MAX.

void *calloc(size_t nmemb, size_t size); can allocate up about SIZE_MAX*SIZE_MAX.

This ability is not often used in many platforms with linear addressing. Such systems limit calloc() with nmemb * size <= SIZE_MAX.

Consider a type of 512 bytes called disk_sector and code wants to use lots of sectors. Here, code can only use up to SIZE_MAX/sizeof disk_sector sectors.

size_t count = SIZE_MAX/sizeof disk_sector;
disk_sector *p = malloc(count * sizeof *p);

Consider the following which allows an even larger allocation.

size_t count = something_in_the_range(SIZE_MAX/sizeof disk_sector + 1, SIZE_MAX)
disk_sector *p = calloc(count, sizeof *p);

Now if such a system can supply such a large allocation is another matter. Most today will not. Yet it has occurred for many years when SIZE_MAX was 65535. Given Moore's law, suspect this will be occurring about 2030 with certain memory models with SIZE_MAX == 4294967295 and memory pools in the 100 of GBytes.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • 2
    Generally, size_t will be capable of holding size of the largest kind of object a program could handle. A system where size_t is 32 bits is unlikely to be able to handle an allocation larger than 4294967295 bytes, and a system that would be able to handle allocations that size would almost certainly make `size_t` larger than 32 bits. The only question is whether using `calloc` with values whose product exceeds `SIZE_MAX` could be relied upon to yield zero rather than returning a pointer to a smaller allocation. – supercat Aug 13 '16 at 21:00
  • Agree about your _generalization_, yet the C spec allows for `calloc()` allocations exceeding `SIZE_MAX`. It has happened in the past with 16-bit `size_t` and as memory continues to cheapen, I see no reason it will cannot happen going forward even if it not _common_. – chux - Reinstate Monica Aug 15 '16 at 01:48
  • 1
    The C Standard makes it possible for code to *request* an allocation whose size exceeds `SIZE_MAX`. It certainly does not require that there be any circumstance under which such an allocation might succeed; I'm not sure there's any particular benefit from mandating that implementations that cannot handle such allocations must return `NULL` (especially given that it's common for some implementations to have `malloc` return pointers to space that's not yet committed and might not be available when code actually tries to use it). – supercat Aug 15 '16 at 15:14
  • Further, where there may have been systems in the past whose available addressing range exceeded the largest representable integer, I do not see any realistic possibility of that ever again occurring, since that would require a storage capacity of billions of gigabytes. Even if Moore's Law continued to hold, going from the point where 32 bits ceases to be enough to the point where 64 bits ceased to be enough would take twice as long as getting from the point where 16 bits was enough to the point where 32 wasn't. – supercat Aug 15 '16 at 15:20
  • @supercat "I'm not sure there's any particular benefit from mandating that implementations that cannot handle such allocations must return NULL " --> A compliant C implementation "The `calloc` function returns either a null pointer or a pointer to the allocated space." It does not exempt a math overflow of `nmemb * size > SIZE_MAX`. – chux - Reinstate Monica Aug 15 '16 at 15:49
  • @supercat "realistic possibility of that ever again occurring, since that would require a storage capacity of billions of gigabytes" --> Memory exceeding 4G is sufficient to consider architectures that would use a `calloc()` that returns a pointers to memory > `SIZE_MAX (4G-1)`. – chux - Reinstate Monica Aug 15 '16 at 15:50
  • 2
    Why would an implementation which can accommodate a single allocation in excess of 4G not define `size_t` to `uint64_t`? – supercat Aug 15 '16 at 17:00
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/120981/discussion-between-chux-and-supercat). – chux - Reinstate Monica Aug 15 '16 at 17:01
0

Both malloc and calloc allocate memory, but calloc initialises all the bits to zero whereas malloc doesn't.

Calloc could be said to be equivalent to malloc + memset with 0 (where memset sets the specified bits of memory to zero).

So if initialization to zero is not necessary, then using malloc could be faster.

Roberto Caboni
  • 7,252
  • 10
  • 25
  • 39
Akshay V
  • 13
  • 3