Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

calloc vs malloc

16 views
Skip to first unread message

lance...@yahoo.com

unread,
Jun 8, 2009, 4:10:54 AM6/8/09
to
Hi,

I'm curious to know if there are any major differences between using
calloc and malloc.

I understand that calloc initializes the variables that it has
allocated memory for (although I remember coming across an article
that says this is not always true), while malloc does not. I also
remember reading somewhere that malloc could be slightly faster than
calloc, though from my personal experience, I don't see a big
difference in terms of speed.

I seem to see people using malloc more, though I prefer calloc because
of the initialization.

So are there any more differences between the two?

Thank you.

Richard Heathfield

unread,
Jun 8, 2009, 4:42:57 AM6/8/09
to
lance...@yahoo.com said:

> Hi,
>
> I'm curious to know if there are any major differences between
> using calloc and malloc.
>
> I understand that calloc initializes the variables that it has
> allocated memory for

Well, it sets the bytes to all-bits-zero, which isn't quite the same
thing.

> (although I remember coming across an article
> that says this is not always true),

Right.

> while malloc does not.

Right again.

> I also remember reading somewhere that malloc could be slightly
> faster than calloc,

It could be. After all, setting bits to zero probably can't be done
in zero time.

> though from my personal experience, I don't see a big
> difference in terms of speed.

Fine, so why worry?

> I seem to see people using malloc more, though I prefer calloc
> because of the initialization.
>
> So are there any more differences between the two?

malloc takes one arg rather than two :-)

In general, malloc is preferred here on the grounds that you're
probably going to set the value to something other than zero pretty
much straight away (and possibly also because it avoids implicit
and perhaps unwise reliance on all-bits-zero meaning 0.0 or NULL
for the relevant types.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Forged article? See
http://www.cpax.org.uk/prg/usenet/comp.lang.c/msgauth.php
"Usenet is a strange place" - dmr 29 July 1999

lance...@yahoo.com

unread,
Jun 8, 2009, 5:45:45 AM6/8/09
to
On Jun 8, 4:42 pm, Richard Heathfield <r...@see.sig.invalid> wrote:
>
> In general, malloc is preferred here on the grounds that you're
> probably going to set the value to something other than zero pretty
> much straight away (and possibly also because it avoids implicit
> and perhaps unwise reliance on all-bits-zero meaning 0.0 or NULL
> for the relevant types.

Say I've allocated a large amount of memory (hundreds of MBs), and
want to initialize all values to zero (the variables are all
integers). Would it not be more efficient to use calloc instead so all
bits are zero upon allocation, instead of explicitly setting every
variable to zero? What about allocating memory for a multi-dimensional
array? Wouldn't looping through the different levels of indices be
more inefficient?

What are the implications of relying the all-bits-zero to mean NULL
when allocating memory for pointers?

Giacomo Degli Esposti

unread,
Jun 8, 2009, 6:19:41 AM6/8/09
to
On 8 Giu, 11:45, "lancer6...@yahoo.com" <lancer6...@yahoo.com> wrote:
> On Jun 8, 4:42 pm, Richard Heathfield <r...@see.sig.invalid> wrote:
> Say I've allocated a large amount of memory (hundreds of MBs), and
> want to initialize all values to zero (the variables are all
> integers). Would it not be more efficient to use calloc instead so all
> bits are zero upon allocation, instead of explicitly setting every
> variable to zero? What about allocating memory for a multi-dimensional
> array? Wouldn't looping through the different levels of indices be
> more inefficient?

Yes, looping is less efficient, but it is necessary when you are
dealing
with pointers and floating point objects, where it is not guaranteed
that
0 bits values correspond to correct values (see below)

> What are the implications of relying the all-bits-zero to mean NULL
> when allocating memory for pointers?

It is not a good thing! :)

Actually, this is a FAQ, more precisely 7.31:

7.31: What's the difference between calloc() and malloc()? Is it
safe
to take advantage of calloc's zero-filling? [...]

A: calloc(m, n) is essentially equivalent to
p = malloc(m * n);
memset(p, 0, m * n);
The zero fill is all-bits-zero, and does *not* therefore
guarantee useful null pointer values (see section 5 of this
list) or floating-point zero values. [...]

ciao
Giacomo


James Kuyper

unread,
Jun 8, 2009, 7:27:51 AM6/8/09
to
lance...@yahoo.com wrote:
> Hi,
>
> I'm curious to know if there are any major differences between using
> calloc and malloc.
>
> I understand that calloc initializes the variables that it has
> allocated memory for (although I remember coming across an article
> that says this is not always true),

If calloc() returns a non-null pointer value, that pointer must point to
a block of memory of at least the requested size (most systems round the
size upward to the next multiple of a block size), and the requested
number of bytes at the beginning of that block must all have a value of
0. If that article suggested otherwise, it was mistaken.

> while malloc does not. I also
> remember reading somewhere that malloc could be slightly faster than

> calloc, ...

That's because it has to zero the allocated memory.

> ... though from my personal experience, I don't see a big


> difference in terms of speed.

No one said it has to be a big difference. You're more likely to see a
noticeable difference if you allocate very large blocks of memory.

> I seem to see people using malloc more, though I prefer calloc because
> of the initialization.

Many people prefer to use malloc(), because they don't want calloc() to
waste time initializing the memory.

> So are there any more differences between the two?

The only other difference is that calloc() takes two arguments,
typically used for the number of elements in an array, and the size of
each element of the array (not necessarily in that order). However, so
long as the mathematical product of those two numbers doesn't exceed
SIZE_MAX, sending those two numbers as separate arguments to calloc() or
sending the product of those numbers to malloc() will allocate the same
amount of memory, with the same restrictions on it's alignment.

James Kuyper

unread,
Jun 8, 2009, 7:41:08 AM6/8/09
to
lance...@yahoo.com wrote:
> On Jun 8, 4:42 pm, Richard Heathfield <r...@see.sig.invalid> wrote:
>> In general, malloc is preferred here on the grounds that you're
>> probably going to set the value to something other than zero pretty
>> much straight away (and possibly also because it avoids implicit
>> and perhaps unwise reliance on all-bits-zero meaning 0.0 or NULL
>> for the relevant types.
>
> Say I've allocated a large amount of memory (hundreds of MBs), and
> want to initialize all values to zero (the variables are all
> integers). Would it not be more efficient to use calloc instead so all
> bits are zero upon allocation, instead of explicitly setting every
> variable to zero?

calloc() might reasonably be implemented as a call to malloc() followed
by a call to memset(), in which case calling malloc() and memset()
yourself might even be slightly faster.

However, Richard Heathfield's main point above is that it is often not
the case that you will want to set all the values to 0. Even if you do
want to, it's not necessarily the case that you're right.

> What about allocating memory for a multi-dimensional
> array? Wouldn't looping through the different levels of indices be
> more inefficient?

If setting every byte of the object to 0 will do the job, looping over
the different levels of indices is not necessary; use memset() instead.
If memset() won't do the job, then neither will calloc(), and the loop
is indeed necessary.

> What are the implications of relying the all-bits-zero to mean NULL
> when allocating memory for pointers?

Code which relies on that assumption will only work on systems where
that assumption is accurate.

Eric Sosman

unread,
Jun 8, 2009, 8:08:24 AM6/8/09
to
lance...@yahoo.com wrote:
> On Jun 8, 4:42 pm, Richard Heathfield <r...@see.sig.invalid> wrote:
>> In general, malloc is preferred here on the grounds that you're
>> probably going to set the value to something other than zero pretty
>> much straight away (and possibly also because it avoids implicit
>> and perhaps unwise reliance on all-bits-zero meaning 0.0 or NULL
>> for the relevant types.
>
> Say I've allocated a large amount of memory (hundreds of MBs), and
> want to initialize all values to zero (the variables are all
> integers).

What is the "information content" of eight hundred
megabits, all zero?

In other words, your scenario is fairly rare. Yes, it
does sometimes happen that you want a big array that is
initially "empty" -- for a hash table, say -- but more often
you'll allocate memory and start filling it with something
meaningful.

> Would it not be more efficient to use calloc instead so all
> bits are zero upon allocation, instead of explicitly setting every
> variable to zero?

It might be. What do your measurements show?

> What about allocating memory for a multi-dimensional
> array? Wouldn't looping through the different levels of indices be
> more inefficient?

"It might be. What do your measurements show?"

> What are the implications of relying the all-bits-zero to mean NULL
> when allocating memory for pointers?

This seems obvious almost to the point of vacuousness.
The implication of "I rely on X" is "If NOT-X, I'm hosed."
Maybe you meant to ask something a little different?

--
Eric Sosman
eso...@ieee-dot-org.invalid

blargg

unread,
Jun 8, 2009, 8:22:06 AM6/8/09
to
James Kuyper wrote:
> lance...@yahoo.com wrote:
> > On Jun 8, 4:42 pm, Richard Heathfield <r...@see.sig.invalid> wrote:
> >> In general, malloc is preferred here on the grounds that you're
> >> probably going to set the value to something other than zero pretty
> >> much straight away (and possibly also because it avoids implicit
> >> and perhaps unwise reliance on all-bits-zero meaning 0.0 or NULL
> >> for the relevant types.
> >
> > Say I've allocated a large amount of memory (hundreds of MBs), and
> > want to initialize all values to zero (the variables are all
> > integers). Would it not be more efficient to use calloc instead so all
> > bits are zero upon allocation, instead of explicitly setting every
> > variable to zero?
>
> calloc() might reasonably be implemented as a call to malloc() followed
> by a call to memset(), in which case calling malloc() and memset()
> yourself might even be slightly faster.

Or you may be on a system that sometimes/always clears memory, even that
from malloc(), in which case calloc() would be more efficient than
malloc() then memset().

Gordon Burditt

unread,
Jun 8, 2009, 3:36:10 PM6/8/09
to
>What are the implications of relying the all-bits-zero to mean NULL
>when allocating memory for pointers?

The C standard does not guarantee that the representation of a
null pointer is 0xdeadbeef, even on machines where pointers are
32 bits. So you might end up with your pointers initialized to
NULL. But don't count on it.

Gene

unread,
Jun 8, 2009, 8:07:33 PM6/8/09
to
On Jun 8, 4:10 am, "lancer6...@yahoo.com" <lancer6...@yahoo.com>
wrote:

In addition to all the other great answers, some operating systems
implement a "lazy" style of malloc() where swap space is not allocated
until a mallocated page is touched. This allows for e.g. a memory
allocation arena where allocated space costs nothing until used. I've
never heard of a calloc() implementation that supported similar
laziness. Since the cost of allocating a page in swap space and
clearing it to bit-zero bytes is likely to be considerable
(milliseconds per page), there is a very meaningful difference between
the two.

Nate Eldredge

unread,
Jun 8, 2009, 8:57:22 PM6/8/09
to
Gene <gene.r...@gmail.com> writes:

> In addition to all the other great answers, some operating systems
> implement a "lazy" style of malloc() where swap space is not allocated
> until a mallocated page is touched. This allows for e.g. a memory
> allocation arena where allocated space costs nothing until used. I've
> never heard of a calloc() implementation that supported similar
> laziness.

FreeBSD's does. Large allocations are handled via anonymous mmap, which
sets aside address space and actually maps in physical pages as they are
touched. These pages are zeroed by the kernel before being mapped in to
avoid information leaks. calloc knows this, and will not try to zero
such allocations itself.

On my 64-bit FreeBSD system, I can call calloc with a size drastically
larger than the amount of memory and swap on the system, and have it
return non-NULL. Reading and writing small portions of this space works
fine; it is read back as zeros. Trying to write to all of it causes the
system to thrash itself to death :)

Tor Rustad

unread,
Jun 9, 2009, 6:10:06 PM6/9/09
to

"Memory is like an orgasm. It's a lot better if you don't have to fake it."
-- Seymour Cray [On virtual memory]


This program was not intended for c.l.c, but a while back I wanted to
check out the infamous OOM killer on Linux.

$ cat oom.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_CHUNKS 1000
#define CHUNK_SIZE (1<<20)

static void usage(const char *error_text)
{
if (error_text)
fprintf(stderr, "Error: %s\n", error_text);
fprintf(stderr, "oom <alloc-type>\n"
"alloc-type : 1-3\n");
exit(EXIT_FAILURE);
}

static void alloc_no_use(size_t msize)
{
int i;

printf("alloc_no_use: ");
for (i = 0;; i++) {
if (NULL == malloc(msize)) {
printf("failure after %d chunks\n", i);
return;
}
}
printf("grabbed %d chunks\n", i);
}

static void alloc_and_touch(size_t msize)
{
int i;

printf("alloc_and_touch: ");
for (i = 0;; i++) {
if (NULL == calloc(1, msize)) {
printf("failure after %d chunks\n", i);
return;
}
}
printf("grabbed %d chunks\n", i);
}

static void alloc_and_use_later(size_t msize)
{
int i, j;
char *chunk[MAX_CHUNKS];


printf("alloc_and_use_later: ");
for (i = 0; i < MAX_CHUNKS; i++) {
chunk[i] = malloc(msize);
if (chunk[i] == NULL) {
printf("grabbed %d chunks\n", i);
break;
}
}
printf("touching chunk: ", i);
for (j = 0; j < i; j++) {
memset(chunk[j], 0, msize);
/*printf("%d ", j);*/
}
puts("Finished!");
}

int main(int argc, char *argv[])
{
if (argc != 2) {
printf("%d", argc);
usage("Wrong arg count");
}

printf("Chunk size for allocator is: %ul\n\n", CHUNK_SIZE);
switch (argv[1][0]) {
case '1':
alloc_no_use(CHUNK_SIZE);
break;
case '2':
alloc_and_touch(CHUNK_SIZE);
break;
case '3':
alloc_and_use_later(CHUNK_SIZE);
break;
default:
usage("alloc-type not supported");
}

return 0;
}

running it on a Linux box:

$ gcc -ansi oom.c -o oom
$ oom 1
Chunk size for allocator is: 1048576

alloc_no_use: failure after 3057 chunks
$ oom 2
Chunk size for allocator is: 1048576

alloc_and_touch: failure after 3057 chunks
$ oom 3
Chunk size for allocator is: 1048576

alloc_and_use_later: grabbed 3056 chunks
touching #3056 chunks
Killed

we see that there is no difference between malloc() and calloc(), both
grab around 3GB, before the allocation fails, even if I only have 1 GB
of memory. On a 32-bit system, process address space is typically
limited to 4 GB.

OOM killer arrives to the scene in the last example, when I run malloc()
& memset() on the allocated blocks, and finally kills the process.

My system is veeeeeeeeeery slow now.

--
Tor <echo bwz...@wvtqvm.vw | tr i-za-h a-z>

chad

unread,
Jun 9, 2009, 11:45:18 PM6/9/09
to
On Jun 8, 3:19 am, Giacomo Degli Esposti


Okay, I'm not drawing a clear distinction between zero bytes and zero
bits.

James Kuyper

unread,
Jun 10, 2009, 5:46:10 AM6/10/09
to
chad wrote:
> On Jun 8, 3:19 am, Giacomo Degli Esposti
> <giacomo.degliespo...@gmail.com> wrote:
>> On 8 Giu, 11:45, "lancer6...@yahoo.com" <lancer6...@yahoo.com> wrote:
...

>> Yes, looping is less efficient, but it is necessary when you are
>> dealing
>> with pointers and floating point objects, where it is not guaranteed
>> that
>> 0 bits values correspond to correct values (see below)
>>
>>> What are the implications of relying the all-bits-zero to mean NULL
>>> when allocating memory for pointers?
>> It is not a good thing! :)
>>
>> Actually, this is a FAQ, more precisely 7.31:
>>
>> 7.31: What's the difference between calloc() and malloc()? Is it
>> safe
>> to take advantage of calloc's zero-filling? [...]
>>
>> A: calloc(m, n) is essentially equivalent to
>> p = malloc(m * n);
>> memset(p, 0, m * n);
>> The zero fill is all-bits-zero, and does *not* therefore
>> guarantee useful null pointer values (see section 5 of this
>> list) or floating-point zero values. [...]
>>
>
>
> Okay, I'm not drawing a clear distinction between zero bytes and zero
> bits.

That is not the distinction that is being made. If all the bits are
zero, then all the bytes (interpreted as unsigned char) must also be 0.
However, if all of the bits (and therefore, all of the bytes) of a
pointer object or of floating point object are 0, the object is not even
guaranteed to contain a valid representation of a value of its type;
it's certainly not guaranteed to contain a representation of a value
that would compares equal to 0.

Nick Keighley

unread,
Jun 11, 2009, 4:25:36 AM6/11/09
to
On 10 June, 04:45, chad <cdal...@gmail.com> wrote:
> On Jun 8, 3:19 am, Giacomo Degli Esposti
> <giacomo.degliespo...@gmail.com> wrote:
> > On 8 Giu, 11:45, "lancer6...@yahoo.com" <lancer6...@yahoo.com> wrote:
> > > On Jun 8, 4:42 pm, Richard Heathfield <r...@see.sig.invalid> wrote:


> > > Say I've allocated a large amount of memory (hundreds of MBs), and
> > > want to initialize all values to zero (the variables are all
> > > integers). Would it not be more efficient to use calloc instead so all
> > > bits are zero upon allocation, instead of explicitly setting every
> > > variable to zero? What about allocating memory for a multi-dimensional
> > > array? Wouldn't looping through the different levels of indices be
> > > more inefficient?
>
> > Yes, looping is less efficient, but it is necessary when you are
> > dealing with pointers and floating point objects, where it is not
> > guaranteed that 0 bits values correspond to correct values (see below)
>
> > > What are the implications of relying the all-bits-zero to mean NULL
> > > when allocating memory for pointers?

it's wrong


> > It is not a good thing! :)
>
> > Actually, this is a FAQ, more precisely 7.31:
>
> > 7.31:   What's the difference between calloc() and malloc()?  Is it
> > safe
> >         to take advantage of calloc's zero-filling?  [...]
>
> > A:      calloc(m, n) is essentially equivalent to
> >                 p = malloc(m * n);
> >                 memset(p, 0, m * n);
> >         The zero fill is all-bits-zero, and does *not* therefore
> >         guarantee useful null pointer values (see section 5 of this
> >         list) or floating-point zero values.  [...]
>
> Okay, I'm not drawing a clear distinction between zero bytes and zero
> bits.

because there isn't one. All the bits are set to zero. All the bytes
are set
to zero. But it is not guarenteed that either the null pointer
constant
or floating point 0.0 have all their constituant bytes set to zero.

#include <stdio.h>

void dump_val (unsigned char *p, size_t n)
{
size_t i;
for (i = 0; i < n; i++)
printf ("%.02x ", *p & 0xff);
printf ("\n");
}

int main (void)
{
void *null = NULL;
double zero = 0.0;
unsigned char *p;

p = (unsigned char*)&null;
printf ("representation of NULL is ");
dump_val (p, sizeof(null));

p = (unsigned char*)&zero;
printf ("representation of 0.0 is ");
dump_val (p, sizeof(zero));

return 0;
}

On most implementations this will print strings of zeros.
But not on all of them.

To be fair IEEE floating point using all-bits-zero
for 0.0 and ABZ is a common design choice for the null
pointer.

But real world implementaions have made different choices.


--
Nick Keighley

Unicode is an international standard character set that can be used
to write documents in almost any language you're likely to speak,
learn or encounter in your lifetime, barring alien abduction.
(XML in a Nutshell)

Richard

unread,
Jun 11, 2009, 6:34:41 AM6/11/09
to
Nick Keighley <nick_keigh...@hotmail.com> writes:

But it is guaranteed that you are still incapable of posting a coherent
paragraph. Could you really not configure your SW properly? And use
capitals?

Kenny McCormack

unread,
Jun 11, 2009, 10:34:46 AM6/11/09
to
In article <h0qmk1$a9h$7...@news.eternal-september.org>,
Richard <rgr...@gmail.com> wrote:
...

>> because there isn't one. All the bits are set to zero. All the bytes
>> are set
>> to zero. But it is not guarenteed that either the null pointer
>> constant
>> or floating point 0.0 have all their constituant bytes set to zero.
>
>But it is guaranteed that you are still incapable of posting a coherent
>paragraph. Could you really not configure your SW properly? And use
>capitals?

I assume that Nick posts under the influence. Generally, when you see
people post basically coherent thoughts (this distinguishes him from the
usual crop of newbies/losers/no-speakaDaEnglit posters) in an incoherent
fashion, the assumption is that they are posting drunk.

Boon

unread,
Jun 11, 2009, 11:53:12 AM6/11/09
to
Nick Keighley wrote:

> #include <stdio.h>
>
> void dump_val (unsigned char *p, size_t n)
> {
> size_t i;
> for (i = 0; i < n; i++)
> printf ("%.02x ", *p & 0xff);
> printf ("\n");
> }

I've often wondered about this kind of code on platforms where CHAR_BIT > 8

Consider a platform where CHAR_BIT = 32 and double is 64-bits wide.
Thus sizeof(double) = 2
Moreover, suppose the representation of 0.0 is 0x0102030405060708

Then
dump_val((unsigned char *)&zero, sizeof(zero));
would just print one of
01 05 (big endian system)
04 08 (little endian system)
0x 0y (other endian system)

Is this correct?

James Kuyper

unread,
Jun 12, 2009, 6:30:55 AM6/12/09
to
Boon wrote:
> Nick Keighley wrote:
>
>> #include <stdio.h>
>>
>> void dump_val (unsigned char *p, size_t n)
>> {
>> size_t i;
>> for (i = 0; i < n; i++)
>> printf ("%.02x ", *p & 0xff);
>> printf ("\n");
>> }
>
> I've often wondered about this kind of code on platforms where CHAR_BIT > 8
>
> Consider a platform where CHAR_BIT = 32 and double is 64-bits wide.
> Thus sizeof(double) = 2
> Moreover, suppose the representation of 0.0 is 0x0102030405060708
>
> Then
> dump_val((unsigned char *)&zero, sizeof(zero));
> would just print one of
> 01 05 (big endian system)
> 04 08 (little endian system)
> 0x 0y (other endian system)
>
> Is this correct?

Sounds reasonable to me, though it would have been less ambiguous if you
had specified the representation of 0.0 in terms of the values of each
byte. I'm not sure if there even are any CHAR_BIT == 32 systems, but I
gather that CHAR_BIT == 16 does actually occur, especially in embedded
systems, and the above code is just as inappropriate on such systems.

zorro

unread,
Jun 12, 2009, 9:17:41 AM6/12/09
to
On 9 Jun, 02:57, Nate Eldredge <n...@vulcan.lan> wrote:

Yes and as I showed down thread, so do Linux.

Both malloc() and calloc(), grabbed around 3GB, which was 1GB more
than my physical + swap mem, and both alloc_no_use() and
alloc_and_touch() returned immediately.

Flash Gordon

unread,
Jun 13, 2009, 2:55:26 AM6/13/09
to
James Kuyper wrote:

<snip>

> Sounds reasonable to me, though it would have been less ambiguous if you
> had specified the representation of 0.0 in terms of the values of each
> byte. I'm not sure if there even are any CHAR_BIT == 32 systems,

There are. What is more there are compilers where CHAR_BIT == 24, such
as
http://dsplabs.cs.upt.ro/dalt/equipment/docs/compilers/56300cc-usrman.pdf
(section 4.4.1 specifies the range of unsigned char as being 0 to 0xFFFFFF)

> but I
> gather that CHAR_BIT == 16 does actually occur, especially in embedded
> systems, and the above code is just as inappropriate on such systems.

I believe it is mainly DSPs rather than embedded systems in general.
--
Flash Gordon

0 new messages