calloc vs malloc

L

lancer6238

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.
 
L

lancer6238

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?
 
G

Giacomo Degli Esposti

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
 
J

James Kuyper

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.
 
J

James Kuyper

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.
 
E

Eric Sosman

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?
 
G

Gene

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.

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.
 
N

Nate Eldredge

Gene said:
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 :)
 
C

chad

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.  [...]


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

James Kuyper

chad said:
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.
 
N

Nick Keighley

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)
 
K

Kenny McCormack

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?[/QUOTE]

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.
 
B

Boon

Nick said:
#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?
 
J

James Kuyper

Boon said:
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.
 
Z

zorro

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 :)

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.
 
F

Flash Gordon

James Kuyper wrote:

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top