difference between malloc and calloc?

V

venkatesh

hai to everybody,
i am having doubt in difference between the malloc
and calloc function.
please tell where to use and when to use those functions?
 
M

Markus Becker

venkatesh said:
hai to everybody,
i am having doubt in difference between the malloc
and calloc function.
please tell where to use and when to use those functions?

malloc takes one parameter (number of chars to allocate) and
does not initialize the allocated memory, whereas calloc takes
two parameters (number of elements and number of chars per
element) and initialises the allocated memory to zero.

Examples:

// This allocats 500 ints, it does not initialize the memory:
int *m = malloc(500*sizeof(int));

// This, too, allocates 500 ints, but initializes the memory
// to zero:
int *c = calloc(500,sizeof(int));

hth.

Markus
 
E

Eric Sosman

venkatesh said:
hai to everybody,
i am having doubt in difference between the malloc
and calloc function.
please tell where to use and when to use those functions?

Markus Becker has explained the difference. The second
part of your question is about which function to use under
what circumstances, and my suggestion is "Use malloc() almost
always and calloc() almost never."

The reason is that the initialization to zero that calloc()
performs is usually not very helpful:

- The initialization to "all-bits-zero" is not necessarily
the same as initialization to "all-data-zero." C says
very little about the representation of values in memory,
nothing at all for floating-point or pointer values. On
many machines all-bits-zero representations will in fact
correspond to f.p. zeroes or null pointers, but this is
not guaranteed by the language and there have been machines
where the correspondence did not hold. If you get in the
habit of using calloc() to initialize f.p. and pointer
items, you may be heading for trouble.

- Usually, one allocates a chunk of dynamic memory in order
to store something in it -- and when you store something
in it, you'll overwrite whatever was there before. Thus,
the initialization performed by calloc() is usually not
needed anyhow. There are occasional exceptions where all-
bits-zero initialization is helpful, but they are unusual.
Not unheard-of, I grant, but unusual.

There's one possible advantage I can imagine for calloc() over
malloc(), and that's the opportunity for a tiny bit of sanity-
checking. Here are two ways you might try to allocate memory to
hold N items of SomeType:

SomeType *p = malloc(N * sizeof *p);
SomeType *q = calloc(N, sizeof *q);

Now, if N is so large that multiplying it by sizeof(SomeType)
exceeds the valid range of size_t, the argument in the first
form will "wrap around" and you'll silently request less memory
than you wanted; if the request succeeds you'll proceed merrily
along and try to store N items in too small a space, with the
usually unhappy and sometimes baffling consequences. The second
form, however, will fail and return NULL so your program will be
alerted that the space was not available; there'll be no silent
error. However, this seems to me to be a very small advantage,
so I'll stick with my original suggestion: malloc() almost always,
calloc() almost never.
 
S

Simon Biber

Eric said:
There's one possible advantage I can imagine for calloc() over
malloc(), and that's the opportunity for a tiny bit of sanity-
checking. Here are two ways you might try to allocate memory to
hold N items of SomeType:

SomeType *p = malloc(N * sizeof *p);
SomeType *q = calloc(N, sizeof *q);

Now, if N is so large that multiplying it by sizeof(SomeType)
exceeds the valid range of size_t, the argument in the first
form will "wrap around" and you'll silently request less memory
than you wanted; if the request succeeds you'll proceed merrily
along and try to store N items in too small a space, with the
usually unhappy and sometimes baffling consequences. The second
form, however, will fail and return NULL so your program will be
alerted that the space was not available; there'll be no silent
error. However, this seems to me to be a very small advantage,
so I'll stick with my original suggestion: malloc() almost always,
calloc() almost never.

Does this mean that

void *my_calloc1(size_t a, size_t b)
{
void *p = malloc(a * b);
if(p) memset(p, 0, a * b);
return p;
}

would not be a valid implementation of calloc, because of the
possibility of overflow?

If calloc needs to check for overflow in a * b, how should it do so?

void *my_calloc2(size_t a, size_t b)
{
void *p = NULL;
size_t n = a * b;
if(a && b && n / a == b && n / b == a)
{
p = malloc(n);
if(p) memset(p, 0, n);
}
return p;
}

Perhaps this is overkill...
 
P

pete

Simon said:
Does this mean that

void *my_calloc1(size_t a, size_t b)
{
void *p = malloc(a * b);
if(p) memset(p, 0, a * b);
return p;
}

would not be a valid implementation of calloc, because of the
possibility of overflow?

I don't know.
If calloc needs to check for overflow in a * b, how should it do so?

void *my_calloc2(size_t a, size_t b)
{
void *p = NULL;
size_t n = a * b;
if(a && b && n / a == b && n / b == a)
{
p = malloc(n);
if(p) memset(p, 0, n);
}
return p;
}

Perhaps this is overkill...

I think calloc(0) should return the same value as malloc(0),
whatever that may be.

And I think that only one of these checks is needed:
n / a == b && n / b == a

void *my_calloc3(size_t a, size_t b)
{
void *p;
size_t n;

if (a == 0 || b == 0) {
p = malloc(0);
} else {
n = a * b;
if (n / a == b) {
p = malloc(n);
if (p != NULL) {
memset(p, 0, n);
}
} else {
p = NULL;
}
}
return p;
}
 
E

Eric Sosman

Simon said:
Does this mean that

void *my_calloc1(size_t a, size_t b)
{
void *p = malloc(a * b);
if(p) memset(p, 0, a * b);
return p;
}

would not be a valid implementation of calloc, because of the
possibility of overflow?

Yes, I think it would be invalid. The Standard says (in
7.20.3.1)

The calloc function allocates space for an array of
/nmemb/ objects, each of whose size is /size/. [...]

This is subject to the general condition in 7.20.3

[...] If the space cannot be allocated, a null pointer
is returned. [...]

Thus, if calloc() cannot find sufficient space for /nmemb/
objects of /size/ bytes each, it must return NULL. There is no
special dispensation for overflow of nmemb * size; there is just
the requirement for a NULL returned value.
If calloc needs to check for overflow in a * b, how should it do so?

The response by "pete" seems to cover what's needed.
 
P

Peter Nilsson

pete said:
void *my_calloc3(size_t a, size_t b)
{
void *p;
size_t n;

if (a == 0 || b == 0) {
p = malloc(0);
} else {
n = a * b;
if (n / a == b) {

To be pedantic, size_t may theoretically promote to int, which can
overflow.

if (a <= ((size_t) -1) / b) {
n = a * b;
 
P

pete

Jordan said:
Eh? If size_t can promote to int, how can it overflow it?

I suppose if 'a' was lower ranking than int,
like unsigned short or unsigned char,
and the max value for that type was equal to INT_MAX,
and 'a' was equal to INT_MAX and 'b' was greater than 1,
or any other combination where the product of a*b exceded INT_MAX,
then a*b would overflow.

If a byte has enough bits to represent all the positive
values within the range of int,
then an allowable way to implement an int,
is to make sizeof(int) equal to 2,
and use the high order byte just for the sign bit.

I never heard of a size_t lower ranking than unsigned.
It would be strange, but I think it's allowed.
 

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

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,528
Members
45,000
Latest member
MurrayKeync

Latest Threads

Top