difference between calloc() and malloc()

A

acehreli

You shouldn't be using either one in C++ if you can help it. Use
operator new instead.

new constructs objects but malloc and calloc reserve raw memory;
different...

Ali
 
V

Victor Bazarov

new constructs objects but malloc and calloc reserve raw memory;
different...

Well, malloc and calloc are just 'new char[]' and 'new char[]()'.
They don't "reserve raw memory" since there is no "raw memory" in
C++.

V
 
A

acehreli

new constructs objects but malloc and calloc reserve raw memory;
different...

Well, malloc and calloc are just 'new char[]' and 'new char[]()'.
They don't "reserve raw memory" since there is no "raw memory" in
C++.

With "raw memory," I meant the allocated storage that allocators
allocate; you know, to construct objects on... I don't keep a copy of
the standard any more, but I'm pretty sure it talks about storage. I
regret now that I called that "raw memory"...

On your point about using new[] for storage, it is misguided. Because
new char[] allocates uninitialized chars and new char[]() allocates
initialized chars. The behaviour is quite different than allocating
storage to construct objects on. It is possible to construct object on
tops of chars, but it's a side effect of chars having trivial
destructors.

Ali
 
A

acehreli

On your point about using new[] for storage, it is misguided. Because
new char[] allocates uninitialized chars and new char[]() allocates
initialized chars.

Even though I typed "allocates" twice above, I meant "constructs"
twice. My point below is that new[] constructs chars.
The behaviour is quite different than allocating
storage to construct objects on. It is possible to construct object on
tops of chars, but it's a side effect of chars having trivial
destructors.

Ali
 
D

Daniel T.

manish sahu said:
difference between calloc() and malloc()

From http://www.dinkumware.com/manuals/default.aspx

calloc
void *calloc(size_t nelem, size_t size);
The function allocates an array object containing nelem elements each of
size size, stores zeros in all bytes of the array, and returns the
address of the first element of the array if successful; otherwise, it
returns a null pointer.

malloc
void *malloc(size_t size);
The function allocates an object of size size, and returns the address
of the object if successful; otherwise, it returns a null pointer.

See the difference?
 
J

James Kanze

Well, malloc and calloc are just 'new char[]' and 'new
char[]()'. They don't "reserve raw memory" since there is no
"raw memory" in C++.

That's not true. Raw memory is what exists between the moment
the memory is allocated, and the moment the constructor is run,
or between the moment the destructor finishes and the moment the
memory is freed. Call reserve() on an empty std::vector, and
that vector will contain raw memory.

The way raw memory is usually allocated in C++ is by calling the
operator new() function. malloc() can also be used. calloc()
should probably be avoided, both in C and in C++, because it
masks a number of serious errors.
 
J

Jeff Schwab

James said:
The way raw memory is usually allocated in C++ is by calling the
operator new() function. malloc() can also be used. calloc()
should probably be avoided, both in C and in C++, because it
masks a number of serious errors.

What are the problems with calloc? Googling "calloc errors" and
"problems with calloc" did not turn up anything obvious.
 
P

Pete Becker

What are the problems with calloc? Googling "calloc errors" and
"problems with calloc" did not turn up anything obvious.

It sets all the bytes in the allocated memory to 0. All too often, that
will mean that uninitialized data members look like they have
legitimate values.
 
J

Jeff Schwab

Pete said:
It sets all the bytes in the allocated memory to 0. All too often, that
will mean that uninitialized data members look like they have legitimate
values.

Huh? That's not only the documented behavior, it's the primary reason
to use calloc. I specifically have used it in the past to avoid having
to zero-out memory manually, which I do to make sure that the program's
behavior is at least deterministic. This is considered a bad thing?
 
V

Victor Bazarov

Jeff said:
Huh? That's not only the documented behavior, it's the primary reason
to use calloc. I specifically have used it in the past to avoid
having to zero-out memory manually, which I do to make sure that the
program's behavior is at least deterministic. This is considered a
bad thing?

I believe what Pete refers to is, if you forget to initialise
a member to something meaningful, then the use of 'calloc' when
allocating your class object dynamically would hide the fact
that you didn't initialise that member, and instead create
a false sense of security. When an object of the same type is
instantiated in automatic storage (local object, argument), the
uninitialised member will play some role, possibly detrimental,
and the bug would be difficult to track.

V
 
J

Jeff Schwab

Victor said:
I believe what Pete refers to is, if you forget to initialise
a member to something meaningful, then the use of 'calloc' when
allocating your class object dynamically would hide the fact
that you didn't initialise that member, and instead create
a false sense of security. When an object of the same type is
instantiated in automatic storage (local object, argument), the
uninitialised member will play some role, possibly detrimental,
and the bug would be difficult to track.

Thank you, that makes some sense. I guess I'm at odds with the
prevailing wisdom here, though. I still prefer this:

auto primitive_t a[size] = { 0 };

To that:

auto primitive_t b[size];

If a local vector is used rather than an array (or a calloc'd block of
memory), I'm not even sure how to specify that the memory should be left
uninitialized...

auto std::vector<primitive_t> v(size, ?);

AFAIK, static objects are guaranteed to be zero'd by all conformant
implementations, too. I understand the reasoning that random-valued
memory may cause run-time errors (due to improper initialization of data
structures) to occur sooner than they would if memory were always
zero-valued to start; however, I don't see the case of manually
requested, dynamically allocated memory as being so special that garbage
values are, in this one case, preferable to zeros.
 
V

Victor Bazarov

Jeff said:
[..] I don't see the case of manually
requested, dynamically allocated memory as being so special that
garbage values are, in this one case, preferable to zeros.

I don't have any numbers, but the common sense suggests that
initialising to "all bytes zero" is slower than *not* doing it.
So, when you're allocating "raw memory" (OK, I'll concede there
is such a thing) for classes that do have their own constructors
which supposedly initialise the members as needed, would be
better done by malloc than calloc because (a) it's faster and
(b) it does not hide any errors due to missed initialisers.

I believe we are not talking about arrays of primitive types
here.

V
 
J

Jeff Schwab

Victor said:
Jeff said:
[..] I don't see the case of manually
requested, dynamically allocated memory as being so special that
garbage values are, in this one case, preferable to zeros.

I don't have any numbers, but the common sense suggests that
initialising to "all bytes zero" is slower than *not* doing it.
So, when you're allocating "raw memory" (OK, I'll concede there
is such a thing) for classes that do have their own constructors
which supposedly initialise the members as needed, would be
better done by malloc than calloc because (a) it's faster and
(b) it does not hide any errors due to missed initialisers.

It might, though of course it's less likely to. It may be that a char
(bool, pointer...) is supposed to be initialized to a non-zero value,
and that zeroing out the memory would show the error sooner than leaving
a (probably non-zero) value.

Both of your points (speed and early error detection) are good ones, but
are they compelling enough to give up determinism? Doesn't something
like this:

auto T[size];

make you nervous? Actually, while we're on the topic, I notice that
trying to initialize a tr1::array with { 0 } generates a diagnostic from
g++; that makes me nervous, but maybe it's by design. No sir, I don't
like it. :-/
I believe we are not talking about arrays of primitive types
here.

I was thinking of POD here, but I don't think the issues are
POD-specific (unless the correct initialization of a particular array of
POD is to zero its elements.) Any code calling malloc will presumably
have to assign valid data to the memory anyway, whether it be through
explicit assignments or placement-new constructor calls.
 
J

Jack Klein

It sets all the bytes in the allocated memory to 0. All too often, that
will mean that uninitialized data members look like they have
legitimate values.

....as opposed to producing undefined value when the uninitialized data
members are read to determine whether they are valid?

I'll admit that calloc() is not often useful in either C or C++, but
there are occasional times when it, even in C++.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
 
J

James Kanze

What are the problems with calloc?

Using uninitialized memory is an error. Calloc sets all of the
bytes to 0, which happens to correspond to zero initialization
on a lot of systems BUT is not necessarily the case. If your
code counts on zero initialization, using calloc will typically
mask the error (until you have to port to a machine where null
pointers aren't all 0 bits, or some such).

A more reasonable choice would be to initialize all of the
memory with some easily identifiable pattern which probably
won't work---0xDEADBEEF is a popular choice.

An even more reasonable choice, of course, is to use new:).
 
J

James Kanze

Thank you, that makes some sense. I guess I'm at odds with the
prevailing wisdom here, though. I still prefer this:
auto primitive_t a[size] = { 0 };
auto primitive_t b[size];

Yes, but that's not what calloc does. Calloc sets all of the
bits in the memory to 0, regardless of the type. Consider
something like:

void* a[ size ] = {0} ;

This initializes the array with null pointers. Calloc only
initializes the allocated memory with null pointers IF a null
pointer is represented by all bits 0, which while frequent,
isn't necessarily the case. So if you test on a machine where
null pointers are all bits 0, you have the impression that the
code works, even though you haven't correctly initialized the
memory.
If a local vector is used rather than an array (or a calloc'd block of
memory), I'm not even sure how to specify that the memory should be left
uninitialized...
auto std::vector<primitive_t> v(size, ?);

You can't. std::vector does not allow uninitialized objects.
It can't---an uninitialized object is not copiable (unless it is
of character type).
AFAIK, static objects are guaranteed to be zero'd by all conformant
implementations, too.

They are guaranteed to be "zero initialized". That doesn't
necessarily mean all bits 0.
 
J

Jeff Schwab

James said:
Thank you, that makes some sense. I guess I'm at odds with the
prevailing wisdom here, though. I still prefer this:
auto primitive_t a[size] = { 0 };
auto primitive_t b[size];

Yes, but that's not what calloc does. Calloc sets all of the
bits in the memory to 0, regardless of the type. Consider
something like:

void* a[ size ] = {0} ;

This initializes the array with null pointers. Calloc only
initializes the allocated memory with null pointers IF a null
pointer is represented by all bits 0, which while frequent,
isn't necessarily the case. So if you test on a machine where
null pointers are all bits 0, you have the impression that the
code works, even though you haven't correctly initialized the
memory.
If a local vector is used rather than an array (or a calloc'd block of
memory), I'm not even sure how to specify that the memory should be left
uninitialized...
auto std::vector<primitive_t> v(size, ?);

You can't. std::vector does not allow uninitialized objects.
It can't---an uninitialized object is not copiable (unless it is
of character type).
AFAIK, static objects are guaranteed to be zero'd by all conformant
implementations, too.

They are guaranteed to be "zero initialized". That doesn't
necessarily mean all bits 0.

That is an interesting distinction. Do you happen to know of any modern
platforms for which "zero initialized" POD objects require memory with
non-zero bit-patterns?

I spent some years working with microprocessor design teams, and
0xdeadbeef was a common starting value for buses during simulations, to
make it clear that no value had yet been assigned to the bus. The only
time I've seen even a vaguely similar technique used in software is for
the magic numbers that sometimes identify file types, e.g. the
0xcafebabe at the beginning of Java .class files. Unless calloc is
replaced by "deadballoc" or the like, I still prefer zero-valued memory
to residual-junk-valued memory.

And I agree of course, that new is a better option than malloc or calloc
in the vast majority of cases, anyway.
 

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,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top