What is the advantage of malloc over calloc

P

pemo

Richard said:
Why? If your program has no bugs, then you will not use these values,
so it makes no difference what they are. If your program does have
bugs, then random values may well cause the error to be spotted sooner
than null pointers and 0.0 floats.

<snip>

In the case where 0 is *not* a valid value, a check, looping and dividing by
the contents of each vector element would show if there's an error ...
whereas, by some other random [non-zero] value would not.

I think I'd go with zero'ed memory vs. random [esp. during early
development].
 
R

Richard G. Riley

Richard said:
There is no requirement that the bytes of a null pointer be zeroes.
A program that assumes that there is - because it's been tried on
machines where null pointers have zero bytes - will likely break
when it encounters an implementation where null pointers have interesting
bit-patterns.

[Note that the standard /does/ require that a null pointer compare equal
to a literal 0; this is not the same case.]

I must say that in many years of programming it is the first time I
have come across this. I stand corrected. Makes me wonder about the
usefulness of calloc after all.

Do you know of a platform where "Null" pointers did not cast to zero?

Casting is something else again [1]: the issue above was about whether
a pointer with all bytes (or bits) zero was necessarily a null
pointer.

I know. Hence I asked when you have seen a NULL pointer not being byte
equivalent to 0.
If I remember Chris Torek's posts on this subject correctly, the Prime
series of computers had null pointers which had set bits in them (for
capabilities). Hence callocated memory treated as pointers would have
illegal values in, or values pointing /at/ something - but they would
not be /null/ ....

I'll keep that in mind ..
 
C

Chris Torek

I never actually used one myself, but the really old PR1MEs had
48-bit "char *", 32-bit for everything else (this was before
"void *"). Pointers had "address" and "segment" components.
Internally, NULL pointers were represented using a special segment
number (0777 or something like that), as the machine had an
instruction to test for "null pointer" by checking for this
segment number.

Later versions of C on the PR1ME actually used *new hardware*: they
added an instruction, spelled TCNP in assembler, which stood for
"Test C Null Pointer". This new instruction tested the "address"
part for zero, instead of the segment part for 0777 (or whatever
it was).

I'll keep that in mind ..

In case you ever program a PR1ME? :)
 
K

Keith Thompson

Richard G. Riley said:
Richard G. Riley wrote: [...]
Do you know of a platform where "Null" pointers did not cast to zero?

Casting is something else again [1]: the issue above was about whether
a pointer with all bytes (or bits) zero was necessarily a null
pointer.

I know. Hence I asked when you have seen a NULL pointer not being byte
equivalent to 0.

I'm sure that's what you meant, but it's not what you actually wrote;
see above.
 
M

Michael Wojcik

It's not better if the program immediately sets the contents to some
other value. Indeed it's worse, since you've just wasted cycles and
potentially lost locality of reference. If you're using a system
with lazy allocation, you've also just potentially committed a lot of
pages that you might not actually need.
values,

Unless of course the zeroed memory was to hold a set of pointers and a
non null value indicates a valid pointer.

That's what we call a "bug". It's excluded by Richard Tobin's
explicit condition "has no bugs".

And zeroing memory, as calloc does, is not guaranteed to produce a
null pointer value, as I'm sure other people have already pointed
out.
But this does not in any way invalidate the need/requirement for auto
zeroing in a memory allocation call.

That's true in a strictly limited sense (if there is any such
requirement, which frankly I do not believe is often the case).
However, the existence of any such requirement equally does not
remove the justification Richard Tobin described for *not*
initializing memory.

Far better, in most cases, that the program allocate memory and then
immediately initialize it explicitly and properly in a type-safe
manner. (Note that may not entail touching every single byte as
calloc does; the data structure being allocated may use a sentinel or
some other length indicator to separate valid from invalid data.)

That way, the program can do just as much work as necessary; it can
commit just as much memory as necessary; it can initialize each field
correctly; it can let the compiler catch certain errors; and it can
document its intentions for maintainers.

The only case where calloc has any advantage, as far as I can tell,
is if a program actually needs to set an entire allocated area to
all-bits-zero, and this happens in a performance-critical area,
because it's conceivable that there might be some small performance
benefit in that case. But if memory allocation is being done in a
performance-critical area there are likely other more significant
optimizations to be made.

--
Michael Wojcik (e-mail address removed)

An intense imaginative activity accompanied by a psychological and moral
passivity is bound eventually to result in a curbing of the growth to
maturity and in consequent artistic repetitiveness and stultification.
-- D. S. Savage
 
M

Michael Wojcik

... I'd suggest that much C programming may be 'easier' if the default
function of choice was calloc(), which always zeroes memory, and for those
that require it, a function named randalloc() be available which fills
memory with random, or hazardous, bytes (if memset() is insufficient).

This would have dreadful consequences on a lazy-allocating system.
And lazy-allocating systems are common.

It would have adverse consequences on a system with paged virtual
memory and/or memory caching. And those are even more common.

It's very common for C programs to allocate more memory than they
actually use. In fact, this is recommended practice in many
quarters for certain situations - for example to reduce the number
of calls to realloc when enlarging a buffer as it accumulates data.
Such programs, when running on modern general-purpose systems with
caching and paged virtual memory, gain significant benefits if they
avoid touching pages they don't need.

There are far better ways to avoid operating on uninitialized data
than to initialize it all as soon as you get it. Just because C
doesn't provide syntactic sugar for constructors and destructors
doesn't mean you can't allocate and discard objects through factory
and disposal functions that are type-safe, simple, and easy to check
for correctness. For that matter, C supports ADTs very well, via
pointers to incomplete structures; it's really not hard to produce
well-layered code that avoids invalid dereferences. And you get much
more in the bargain, like type-safety and strong interfaces.

--
Michael Wojcik (e-mail address removed)

I will shoue the world one of the grate Wonders of the world in 15
months if Now man mourders me in Dors or out Dors
-- "Lord" Timothy Dexter, _A Pickle for the Knowing Ones_
 
R

Richard Tobin

... I'd suggest that much C programming may be 'easier' if the default
function of choice was calloc(), which always zeroes memory, and for those
that require it, a function named randalloc() be available which fills
memory with random, or hazardous, bytes (if memset() is insufficient).
[/QUOTE]
This would have dreadful consequences on a lazy-allocating system.

It would be easy enough to add operating system support for it. Most
OSes can provide memory pages which are zeroed when they are first
accessed, and providing pages that are randomly-filled when first
accessed would not be hard.

-- Richard
 
C

Chris McDonald

It would be easy enough to add operating system support for it. Most
OSes can provide memory pages which are zeroed when they are first
accessed, and providing pages that are randomly-filled when first
accessed would not be hard.


My understanding, after being berated many times by the learned
contributors to this newsgroup, is that the language's design should
not bow down to any specific type of architecture. Yes, a percentage
of architectures may have 'dreadful consequences' *for them*.

As Richard has indicated, if today's lazy-allocating systems don't already
zero-fill memory, then their calloc()s must be zero-filling the memory
after the operating system has provided it. Thus, this is no different
than random-filling it (which, I suspect, few operating systems provide).
 
M

Michael Wojcik

This would have dreadful consequences on a lazy-allocating system.

It would be easy enough to add operating system support for it. Most
OSes can provide memory pages which are zeroed when they are first
accessed, and providing pages that are randomly-filled when first
accessed would not be hard.[/QUOTE]

But the allocation functions would then have to be able to
distinguish between pages which were reused from previously allocated
and freed memory (which would not be "first accessed", from the OS's
point of view) and those that were freshly allocated from the OS
(which the allocation should not touch, lest they be committed).

It's a significant complication for little benefit, and more benefit
is easily achieved by adopting better programming habits in the
first place.
 
M

Michael Wojcik

My understanding, after being berated many times by the learned
contributors to this newsgroup, is that the language's design should
not bow down to any specific type of architecture.

Nor should it go out of its way to impose inefficiencies on common
platforms.
Yes, a percentage of architectures may have 'dreadful consequences'
*for them*.

Including the platforms which represent a majority of the targets for
hosted C development.
As Richard has indicated, if today's lazy-allocating systems don't already
zero-fill memory, then their calloc()s must be zero-filling the memory
after the operating system has provided it.

See my response to Richard. This is not a fix.

Your proposal asks the language to do extra work and waste resources
in a weak effort to save lazy programmers from themselves. That's
contrary to the spirit of C, and of dubious value in any event.
 
C

Chris McDonald

Nor should it go out of its way to impose inefficiencies on common
platforms.

Agreed - I never proposed deliberately imposing inefficiencies -
but that may have been a consequence.
I was discussing a possible approach that may have made some programming easier.

Including the platforms which represent a majority of the targets for
hosted C development.

Arguments about language and library design, that too early focus on
implementation efficiencies, tend to constrain thinking and finish
prematurely. Fortunately functional, Lisp, and scripting programmers
didn't give up so early. I fully appreciate that standard C won't be
changing in this direction, but parties that justify the status-quo
because of majorities, also seem to tolerate viruses and keyloggers,
and believe that big-endian IPv4 addresses must be evil.

Your proposal asks the language to do extra work and waste resources
in a weak effort to save lazy programmers from themselves. That's
contrary to the spirit of C, and of dubious value in any event.

Strong language.
That's a 20 year view of what a programming language is supposed to provide -
to have a first priority of maximising execution efficiency, and not
assisting programmers if possible.

A more contemporary view is to increase the expressiveness of languages
(we see this with the introduction of C's enumerated types and Booleans)
and, yes, to often save lazy programmers from themselves (C no longer has
assumed integer types and requires prototypes and, of course <OT>Java</OT>
does lots of this).

Yes, extra work may be required, resources can be considered as being
there to be used, and whether the effort is weak or not has been the
focus of this whole thread. There are valid opinions on both sides;
yours has been one.
 
R

Richard G. Riley

That's a 20 year view of what a programming language is supposed to provide -
to have a first priority of maximising execution efficiency, and not
assisting programmers if possible.

Personally I hope C doesnt evolve in the same way some others have. C is
one of the few that almost gives you the reigns and allows you make
your machine trot when it should trot and canter when it should
canter. I've been keeping an eye on the development of Java and it its
still doing a good job of pushing new HW to its limits :-;
 
A

Andrey Tarasevich

Richard said:
There is no requirement that the bytes of a null pointer be zeroes.
A program that assumes that there is - because it's been tried on
machines where null pointers have zero bytes - will likely break
when it encounters an implementation where null pointers have interesting
bit-patterns.

[Note that the standard /does/ require that a null pointer compare equal
to a literal 0; this is not the same case.]

I must say that in many years of programming it is the first time I
have come across this. I stand corrected. Makes me wonder about the
usefulness of calloc after all.

Do you know of a platform where "Null" pointers did not cast to zero?
...

It is probably worth adding that the only objects that can be correctly
initialized with 'calloc' ('memset' to 0, etc.) are objects of type
'[signed/unsigned] char' (and, of course, aggregates composed of these types).
There's a known proposal to modify C standard and make this kind of low-level
initialization to produce defined result for all _integral_ types.
Unfortunately, I don't know the current status of the proposal.
 
J

Jordan Abel

Richard said:
There is no requirement that the bytes of a null pointer be zeroes.
A program that assumes that there is - because it's been tried on
machines where null pointers have zero bytes - will likely break
when it encounters an implementation where null pointers have interesting
bit-patterns.

[Note that the standard /does/ require that a null pointer compare equal
to a literal 0; this is not the same case.]

I must say that in many years of programming it is the first time I
have come across this. I stand corrected. Makes me wonder about the
usefulness of calloc after all.

Do you know of a platform where "Null" pointers did not cast to zero?
...

It is probably worth adding that the only objects that can be correctly
initialized with 'calloc' ('memset' to 0, etc.) are objects of type
'[signed/unsigned] char' (and, of course, aggregates composed of these types).
There's a known proposal to modify C standard and make this kind of low-level
initialization to produce defined result for all _integral_ types.
Unfortunately, I don't know the current status of the proposal.

The standard _does_ guarantee it for integral types, IIRC.
 
A

Andrey Tarasevich

Jordan said:
Richard said:
There is no requirement that the bytes of a null pointer be zeroes.
A program that assumes that there is - because it's been tried on
machines where null pointers have zero bytes - will likely break
when it encounters an implementation where null pointers have interesting
bit-patterns.

[Note that the standard /does/ require that a null pointer compare equal
to a literal 0; this is not the same case.]


I must say that in many years of programming it is the first time I
have come across this. I stand corrected. Makes me wonder about the
usefulness of calloc after all.

Do you know of a platform where "Null" pointers did not cast to zero?
...

It is probably worth adding that the only objects that can be correctly
initialized with 'calloc' ('memset' to 0, etc.) are objects of type
'[signed/unsigned] char' (and, of course, aggregates composed of these types).
There's a known proposal to modify C standard and make this kind of low-level
initialization to produce defined result for all _integral_ types.
Unfortunately, I don't know the current status of the proposal.

The standard _does_ guarantee it for integral types, IIRC.

The C89/90 and original version of C99 did not. The issue here is that the above
method of "initialization" affects padding bits, which might be present in any
integral type other than '[signed/unsigned] char'. And it is not guaranteed that
all-zero bit pattern in both padding and value-representing bits of such
integral type constitutes a valid (non-trap) combination of bits for an object
of such type.

The key point of proposal was to force all implementations to treat all-zero bit
pattern in both padding and value-representing bits as legal.
 
K

Keith Thompson

Andrey Tarasevich said:
It is probably worth adding that the only objects that can be
correctly initialized with 'calloc' ('memset' to 0, etc.) are
objects of type '[signed/unsigned] char' (and, of course, aggregates
composed of these types). There's a known proposal to modify C
standard and make this kind of low-level initialization to produce
defined result for all _integral_ types. Unfortunately, I don't
know the current status of the proposal.

It's been approved and is now effectively part of the standard.

The defect report is at
<http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_263.htm>.
Its status is "Closed, published in TC 2". You can see the
update in the freely available n1124.pdf, which incorporates
the C99 standard plus TC1 and TC2:

6.2.6.2p5:
[...] For any integer type, the object representation where all
the bits are zero shall be a representation of the value zero in
that type.

In n1124.pdf, differences from the original C99 standard are marked
with change bars.
 
S

S.Tobias

Andrey Tarasevich said:
Jordan said:
It is probably worth adding that the only objects that can be correctly
initialized with 'calloc' ('memset' to 0, etc.) are objects of type
'[signed/unsigned] char' (and, of course, aggregates composed of these types).
There's a known proposal to modify C standard and make this kind of low-level
initialization to produce defined result for all _integral_ types.
Unfortunately, I don't know the current status of the proposal.

The standard _does_ guarantee it for integral types, IIRC.

The C89/90 and original version of C99 did not. The issue here is that the above
method of "initialization" affects padding bits, which might be present in any
integral type other than '[signed/unsigned] char'. And it is not guaranteed that
all-zero bit pattern in both padding and value-representing bits of such
integral type constitutes a valid (non-trap) combination of bits for an object
of such type.
....

TC2 (to C99) changed this:

# 9. Page 39, 6.2.6.2
# Append to paragraph 5:
#
# For any integer type, the object representation where all the bits
# are zero shall be a representation of the value zero in that type.
 
C

CBFalconer

S.Tobias said:
.... snip ...
The C89/90 and original version of C99 did not. The issue here is
that the above method of "initialization" affects padding bits,
which might be present in any integral type other than '[signed/
unsigned] char'. And it is not guaranteed that all-zero bit
pattern in both padding and value-representing bits of such
integral type constitutes a valid (non-trap) combination of bits
for an object of such type.
...

TC2 (to C99) changed this:

# 9. Page 39, 6.2.6.2
# Append to paragraph 5:
#
# For any integer type, the object representation where all
# the bits are zero shall be a representation of the value
# zero in that type.

IMO this change was only feasible because an extensive search did
not yield any systems in which it did not already hold. The rule
about not breaking existant code is paramount.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
 

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
474,175
Messages
2,570,944
Members
47,492
Latest member
gabbywilliam

Latest Threads

Top