Author Message

I had a chat with the team leader I mentioned previously. I told him I
had discovered a counterargument to his casting of malloc(), and he
replied:

"Being able to be sure of the element size is not enough. You also need
to know the number of the elements. For example, you might want to
allocate 10 foo_t's to variable a and 15 bar_t's to variable b. If you
do not cast malloc(), there is a possibility that you are allocating
a's elements to b and b's elements to a.
"Using p=malloc(10*sizeof(*p)) will not help because it's a problem
with the 10, not with the sizeof(*p). So we need casts to make the
compiler complain if we allocate foo_t's to a bar_t * or vice versa."

Once again, I could not find a counterargument. What do you C gurus

--

| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
| http://www.*-*-*.com/ ~palaste       W++ B OP+                     |
\----------------------------------------- Finland rules! ------------/
"The obvious mathematical breakthrough would be development of an easy way to
factor large prime numbers."
- Bill Gates

Mon, 29 Mar 2004 05:24:23 GMT

Quote:

> I had a chat with the team leader I mentioned previously. I told him I
> had discovered a counterargument to his casting of malloc(), and he
> replied:

> "Being able to be sure of the element size is not enough. You also need
> to know the number of the elements. For example, you might want to
> allocate 10 foo_t's to variable a and 15 bar_t's to variable b. If you
> do not cast malloc(), there is a possibility that you are allocating
> a's elements to b and b's elements to a.

What on earth does this mean?  malloc never allocates the same memory twice
without an intervening free(), so it is impossible to "allocate a's elements"
to anything else.

Quote:
> "Using p=malloc(10*sizeof(*p)) will not help because it's a problem
> with the 10, not with the sizeof(*p). So we need casts to make the
> compiler complain if we allocate foo_t's to a bar_t * or vice versa."

Casting won't force the compiler (or you) to consider 10 one way or the other.
What "problem with the 10" is the team leader talking about?  Why are you using
10 anyway?  Do you have a cabal that emits digits that you then copy into your
programs?  Why don't you declare p as an automatic array of 10 elements to
begin with?  Use a variable or macro name to abstract 10 into the extent of p's
elements -- then you could do sanity checks.  karl m

Mon, 29 Mar 2004 06:00:10 GMT

Quote:

>I had a chat with the team leader I mentioned previously. I told him I
>had discovered a counterargument to his casting of malloc(), and he
>replied:

>"Being able to be sure of the element size is not enough.

That has nothing to do with casting (or not) the
return value from 'malloc()'.

Quote:
> You also need
>to know the number of the elements.

which you specify in the argument to 'malloc()'
e.g.

int *p = malloc(10 * sizeof *p);

Quote:
>For example, you might want to
>allocate 10 foo_t's to variable a and 15 bar_t's to variable b.

foo_t *a = malloc(10 * sizeof *a);

bar_t *b = malloc(15 * sizeof *b);

Note that this syntax works for *any* type.

Quote:
> If you
>do not cast malloc(), there is a possibility that you are allocating
>a's elements to b and b's elements to a.

There is absolutely no possiblity of this, casting
or not.  What hogwash.

Quote:
>"Using p=malloc(10*sizeof(*p)) will not help

If one desires to dynamically allocate ten contiguous
objects of the type of '*p', then it 'helps' quite a bit,
as that's how its done.

Quote:
>because it's a problem
>with the 10, not with the sizeof(*p).

Casting malloc()'s return value has *nothing* to do
with the value of the argument passed to it.
More nonsense.

Quote:
>So we need casts to make the
>compiler complain if we allocate foo_t's to a bar_t * or vice versa."

textbook.  This is pure nonsense.  A cast *inhibits*
type-related compiler 'complaints', it doesn't enable
them.

return type, and about the rules governing implicit
conversions, esp. those for pointers.

Quote:
>Once again, I could not find a counterargument.

K&R II should do nicely.  As would ISO 9899,  of course. :-)

Quote:
>What do you C gurus

position by less than legitimate means. :-)

-Mike

Mon, 29 Mar 2004 07:03:49 GMT

Quote:
> " [...] So we need casts to make the
> compiler complain if we allocate foo_t's to a bar_t * or vice versa."

How is this different from his previous argument?  I found
it essentially the same.

In case if you are not reading the entire thread, here is a
partial summary of the previous thread: the major opponents cite
the case of missing <stdlib.h> combined with malloc casts;
whereas the major supporters cite the case of hidden diagnostics
when <stdlib.h> is there but the malloc casts are removed.  Both
of them could potentially hide a huge bug.

For average programming projects, you probably don't need
malloc casts, because usually their data structures are quite
and is fond of inventing hundreds of novel and deeply-nested data
structures with all sorts of simulated polymorphisms, then you
will love the malloc casts.

Which situation are you in now?

Tak-Shing

Mon, 29 Mar 2004 07:09:25 GMT

Quote:

>> [out-of-context quotes snipped]
>> If you
>>do not cast malloc(), there is a possibility that you are allocating
>>a's elements to b and b's elements to a.

> There is absolutely no possiblity of this, casting
> or not.  What hogwash.

Are you sure?  Consider a heavily simplified scenerio:

#include <stdio.h>
#include <stdlib.h>
#include "foo.h"

void a_func(void *a) {
a_t *foo = (a_t *) a; foo->data = 1;
}

void b_func(void *b) {
b_t *foo = (b_t *) b; foo->data = 2.0;
}

int main(void) {
global = (a_t *) malloc(sizeof *global);
a_func(global);
/* More code here... */
return EXIT_SUCCESS;
}

Everything is working fine until a third party checks in the
following modified code:

foo.h:
struct a_t { int data; };
struct b_t { double data; };
/* a_t */ b_t *global; /* modified by a third party */

This incorrect program will now trigger a compiler warning,
because the Standard guarantees the diagnostic.  This mandatory
warning message is very useful for locating the bug made by the
third party.

Now, do we have the same guarantee if we lose the cast?

main.c:
global = malloc(sizeof *global);

The answer is unfortunately no.  A conforming compiler is
licensed to silently accept this incorrect program when the
malloc cast is omitted.  As this example shows, malloc casts can
be useful at times.

Tak-Shing

Mon, 29 Mar 2004 08:53:20 GMT
I didn't read your previous post, but is it possible you (he) mean:

foo_t *a = malloc(10 * sizeof(foo_t));
bar_t *b = malloc(10 * sizeof(bar_t));

Then without a cast, you could be stupid and do:

foo_t *a = malloc(10 * sizeof(bar_t)); ?

A cast from malloc to foo_t* would prevent this, but I suppose this is one
of the reasons one should use: foo_t *a = malloc(10 * sizeof *a); instead?

I assume this is a discussion about whether to cast from malloc or not? If
that's the case, then I hear everyone say we should NOT cast from malloc,
as it could mean trouble if for example you forget to include the
declaration
of malloc (making it return an int instead of void *), right? But the
compiler
will give you a warning anyway, so what's the problem really?

Then why does K&R say that "The pointer returned by malloc or calloc has
the proper alignment for the object in question, but it must be cast into
the
appropriate type, as in: int *ip; ip = (int *)calloc(n,sizeof(int));"
(section 7.8.5)?

Should we not trust K&R this time, as I'm always told to do? I will cast my
malloc's as K&R does untill someone can explain to me why we should not
cast and why K&R are wrong! ;)

And btw, what does "proper alignment for the object" mean?

Quote:
> I had a chat with the team leader I mentioned previously. I told him I
> had discovered a counterargument to his casting of malloc(), and he
> replied:

> "Being able to be sure of the element size is not enough. You also need
> to know the number of the elements. For example, you might want to
> allocate 10 foo_t's to variable a and 15 bar_t's to variable b. If you
> do not cast malloc(), there is a possibility that you are allocating
> a's elements to b and b's elements to a.
> "Using p=malloc(10*sizeof(*p)) will not help because it's a problem
> with the 10, not with the sizeof(*p). So we need casts to make the
> compiler complain if we allocate foo_t's to a bar_t * or vice versa."

> Once again, I could not find a counterargument. What do you C gurus

> --

> | Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
> | http://www.helsinki.fi/~palaste       W++ B OP+                     |
> \----------------------------------------- Finland rules! ------------/
> "The obvious mathematical breakthrough would be development of an easy way
to
> factor large prime numbers."
>    - Bill Gates

Mon, 29 Mar 2004 09:16:56 GMT

Quote:
>I had a chat with the team leader I mentioned previously. I told him I
>had discovered a counterargument to his casting of malloc(), and he
>replied:

>"Being able to be sure of the element size is not enough. You also need
>to know the number of the elements.

True.

Quote:
>For example, you might want to
>allocate 10 foo_t's to variable a and 15 bar_t's to variable b.

By stating it like this you are demonstrating a fundamental error in
approach. You should be allocating an array of 10 elements for a
specific purpose and an array of 15 elements for another purpose.
The name of the pointer you use should be what indicates that purpose,
not the type. Type is a very blunt tool, the same type can be used for
different things. If you were allocating arrays of integer types the
type doesn't indicate the purpose at all clearly. Even for structures
that is often true. And of course if you were allocating 10 foo_t's and
15 foo_t's then the type doesn't help you at all, it is imperative you
you allocate the right amount to the right *pointer*.

Quote:
>If you
>do not cast malloc(), there is a possibility that you are allocating
>a's elements to b and b's elements to a.

The same possibility exists when you do cast. The cast does not check that
the element count is correct. The important thing is to be able to
see clearly that the number of elements you are allocating is appropriate
for the pointer that is assigned to point to the allocated memory. The
way to do that is to name the pointer clearly so that any discrepancy
is visible when looking at the code. For example

users = malloc(ngroups * sizeof *users);

looks suspicious whereas

users = malloc(nusers * sizeof *users);

makes sense. Adding a cast such as

users = (User *)malloc(ngroups * sizeof *users);

adds nothing useful to this, it is just clutter.

Quote:
>"Using p=malloc(10*sizeof(*p)) will not help because it's a problem
>with the 10, not with the sizeof(*p). So we need casts to make the
>compiler complain if we allocate foo_t's to a bar_t * or vice versa."

Adding a cast will not help at all if there is a problem with the 10.
What you need to do is change p to a meaningful name so that it becomes
obvious that the 10 is wrong. Another principle is to avoi "magic" constants
in code, changing the 10 to a variable or at least a #define that indicates
its purpose is equally as important.

Quote:
>Once again, I could not find a counterargument. What do you C gurus

Neither the premises of the argument nor the conclusions drawn from them
are valid.

--
-----------------------------------------

-----------------------------------------

Mon, 29 Mar 2004 10:23:56 GMT

Quote:

>I didn't read your previous post, but is it possible you (he) mean:

>foo_t *a = malloc(10 * sizeof(foo_t));
>bar_t *b = malloc(10 * sizeof(bar_t));

>Then without a cast, you could be stupid and do:

>foo_t *a = malloc(10 * sizeof(bar_t)); ?

>A cast from malloc to foo_t* would prevent this,

Really? How?  The argument to malloc() is merely
an unsigned integral value, how it's arrived at
is irrelevant.  Casting prevents nothing (other
than the type safety you'd get without it).

Quote:
> but I suppose this is one
>of the reasons one should use: foo_t *a = malloc(10 * sizeof *a); instead?

Yes, I advocate using that form *always*.
Then changing the type doesn't break it.

Quote:

>I assume this is a discussion about whether to cast from malloc or not?

Yes.  That's the subject line, anyway. :-)

Quote:
>If
>that's the case, then I hear everyone say we should NOT cast from malloc,

I say it too.

Quote:
>as it could mean trouble if for example you forget to include the
>declaration
>of malloc (making it return an int instead of void *), right?

Right.

Quote:
>But the
>compiler
>will give you a warning anyway, so what's the problem really?

Casting *inhibits* warnings.

Quote:
>Then why does K&R say that "The pointer returned by malloc or calloc has
>the proper alignment for the object in question, but it must be cast into
>the
>appropriate type, as in: int *ip; ip = (int *)calloc(n,sizeof(int));"
>(section 7.8.5)?

K&R does not define standard C.  ISO 9899 does.

Quote:

>Should we not trust K&R this time, as I'm always told to do?

K&R at one time was the 'de-facto' standard for C, but that's
no longer the case.  While K&R does contain much useful information
about C, it's no longer the final authority.  The ISO standard is.

Quote:
> I will cast my
>malloc's as K&R does untill someone can explain to me why we should not
>cast

It's been explained to death here.  Search the archives.

Quote:
> and why K&R are wrong! ;)

Because ISO came along and changed the rules,
making 'K&R' 'wrong'.

Quote:
>And btw, what does "proper alignment for the object" mean?

=====================
ISO/IEC 9899:1999 (E)
3.2
1 alignment
requirement that objects of a particular type be located on
storage boundaries with addresses that are particular multiples
=====================

-Mike

Mon, 29 Mar 2004 10:17:55 GMT

Quote:

> >I didn't read your previous post, but is it possible you (he) mean:

> >foo_t *a = malloc(10 * sizeof(foo_t));
> >bar_t *b = malloc(10 * sizeof(bar_t));

> >Then without a cast, you could be stupid and do:

> >foo_t *a = malloc(10 * sizeof(bar_t)); ?

> >A cast from malloc to foo_t* would prevent this,

> Really? How?  The argument to malloc() is merely
> an unsigned integral value, how it's arrived at
> is irrelevant.  Casting prevents nothing (other
> than the type safety you'd get without it).

You're right ofcourse. I don't have a clue what I
was thinking. I'm turning lame again. Damn ;)

Quote:
> > but I suppose this is one
> >of the reasons one should use: foo_t *a = malloc(10 * sizeof *a);

> Yes, I advocate using that form *always*.
> Then changing the type doesn't break it.

> >I assume this is a discussion about whether to cast from malloc or not?

> Yes.  That's the subject line, anyway. :-)

No comment ;)

- Show quoted text -

Quote:
> >If that's the case, then I hear everyone say we should NOT cast
> >from malloc,

> I say it too.

> >[snip]
> >Then why does K&R say that "The pointer returned by malloc or calloc has
> >the proper alignment for the object in question, but it must be cast into
> >the appropriate type, as in: int *ip; ip = (int *)calloc(n,sizeof(int));"
> >(section 7.8.5)?

> K&R does not define standard C.  ISO 9899 does.

> >Should we not trust K&R this time, as I'm always told to do?

> K&R at one time was the 'de-facto' standard for C, but that's
> no longer the case.  While K&R does contain much useful information
> about C, it's no longer the final authority.  The ISO standard is.

Guess I have to grab a copy of the ISO 9899 specification then.

Quote:
> > I will cast my malloc's as K&R does untill someone can
> >explain to me why we should not cast

> It's been explained to death here.  Search the archives.

Sure thing.

Quote:
> >[snip]
> >And btw, what does "proper alignment for the object" mean?

> =====================
> ISO/IEC 9899:1999 (E)
>   3.2
> 1 alignment
>   requirement that objects of a particular type be located on
>   storage boundaries with addresses that are particular multiples
> =====================

> [these 'address boundaries' are platform-dependent]

> -Mike

Thanks for your input. I'll shut up now ;)

Thomas

Mon, 29 Mar 2004 10:19:00 GMT

Quote:
> [...]
> Once again, I could not find a counterargument. What do you C gurus

What the ...??? The number of elements (10, 15) has nothing to do with
casting malloc.
If you have tried to find the counterargument then you have understood the
argument. (Did you?) Can you explain it in a different way?

Regards,
Daniel Dekany

Mon, 29 Mar 2004 10:51:30 GMT

Quote:
>... why does K&R say that "The pointer returned by malloc or calloc has
>the proper alignment for the object in question, but it must be cast into
>the
>appropriate type, as in: int *ip; ip = (int *)calloc(n,sizeof(int));"
>(section 7.8.5)?

>Should we not trust K&R this time, as I'm always told to do? I will cast my
>malloc's as K&R does untill someone can explain to me why we should not
>cast and why K&R are wrong! ;)

This is indeed one of the relatively few glitches in K&R.

In Classic C, malloc() and calloc() had return type "char *", but
this was changed in 1989 and the need for the cast was removed.
Since pointer casts' main function is to disguise bugs, those of
us who have been using C since 1981 prefer to avoid them. :-)

Quote:
>And btw, what does "proper alignment for the object" mean?

See another ongoing topic with the word "cast" in the title.
--
In-Real-Life: Chris Torek, Wind River Systems (BSD engineering)

Mon, 29 Mar 2004 11:21:06 GMT

Quote:
>"Being able to be sure of the element size is not enough. You also need
>to know the number of the elements. For example, you might want to
>allocate 10 foo_t's to variable a and 15 bar_t's to variable b. If you
>do not cast malloc(), there is a possibility that you are allocating
>a's elements to b and b's elements to a.

If the number of elements to allocate space for is based on the type
rather than on what the pointer you're pointing at the allocated memory
is used for, then there are bigger problems than possibly getting the
type/number of elements match wrong.

Quote:
>"Using p=malloc(10*sizeof(*p)) will not help because it's a problem
>with the 10, not with the sizeof(*p). So we need casts to make the
>compiler complain if we allocate foo_t's to a bar_t * or vice versa."

...which works until we forget whether we wanted 10 foo_ts or 10
bar_ts.  Which is at least as likely to happen as forgetting whether it
was a or b that we wanted pointing at space allocated for ten
elements.

Quote:
>Once again, I could not find a counterargument. What do you C gurus

It looks to me like he doesn't want to admit that he was wrong but is
running out of ways to `prove' he's right.
Should that happen to not be the case, you may want to find out what
he's been smoking (and whether he has any to share, if you're into that
sort of thing - but not while you're coding, please).

dave

--

I think you need a scanf expert to check out your program. I've only been
doing C for about eleven and a half years, so IMHO I'm not really ready
for scanf yet.                        --Richard Heathfield in comp.lang.c

Mon, 29 Mar 2004 11:59:16 GMT
[This will probably be the second copy of this post; my newsreader
appeares to have eaten the last try, and posts that that happens to
have a {*filter*} habit of showing up on my newsswerver thirty seconds
*after* I post them again (unless, of course, I don't post them again,
in which case they don't show up at all).]

Quote:
>"Being able to be sure of the element size is not enough. You also need
>to know the number of the elements. For example, you might want to
>allocate 10 foo_t's to variable a and 15 bar_t's to variable b. If you
>do not cast malloc(), there is a possibility that you are allocating
>a's elements to b and b's elements to a.

If the number of elements to allocate space for is based on the type
rather than on what the pointer you're pointing at the allocated memory
is used for, then there are bigger problems than possibly getting the
type/number of elements match wrong.

Quote:
>"Using p=malloc(10*sizeof(*p)) will not help because it's a problem
>with the 10, not with the sizeof(*p). So we need casts to make the
>compiler complain if we allocate foo_t's to a bar_t * or vice versa."

...which works until we forget whether we wanted 10 foo_ts or 10
bar_ts.  Which is at least as likely to happen as forgetting whether it
was a or b that we wanted pointing at space allocated for ten
elements.

Quote:
>Once again, I could not find a counterargument. What do you C gurus

It looks to me like he doesn't want to admit that he was wrong but is
running out of ways to `prove' he's right.
Should that happen to not be the case, you may want to find out what
he's been smoking (and whether he has any to share, if you're into that
sort of thing - but not while you're coding, please).

dave

--

I think you need a scanf expert to check out your program. I've only been
doing C for about eleven and a half years, so IMHO I'm not really ready
for scanf yet.                        --Richard Heathfield in comp.lang.c

Mon, 29 Mar 2004 12:07:44 GMT

Quote:

> I assume this is a discussion about whether to cast from malloc or not? If
> that's the case, then I hear everyone say we should NOT cast from malloc,
> as it could mean trouble if for example you forget to include the
> declaration
> of malloc (making it return an int instead of void *), right? But the
> compiler
> will give you a warning anyway, so what's the problem really?

If you cast, it is not required to give that warning. This is kind of
the point.

Quote:

> Then why does K&R say that "The pointer returned by malloc or calloc has
> the proper alignment for the object in question, but it must be cast into
> the
> appropriate type, as in: int *ip; ip = (int *)calloc(n,sizeof(int));"
> (section 7.8.5)?

> Should we not trust K&R this time, as I'm always told to do? I will cast my
> malloc's as K&R does untill someone can explain to me why we should not
> cast and why K&R are wrong! ;)

http://cm.bell-labs.com/cm/cs/cbook/2ediffs.html says:

"142: The remark about casting the return value of malloc ("the proper
method is to declare ... then explicitly coerce") needs to be rewritten.
The example is correct and works, but the advice is debatable in the
context of the 1988-1989 ANSI/ISO standards. It's not necessary (given
that coercion of void * to ALMOSTANYTYPE * is automatic), and possibly
harmful if malloc, or a proxy for it, fails to be declared as returning
void *. The explicit cast can cover up an unintended error. On the other
hand, pre-ANSI, the cast was necessary, and it is in C++ also. "

I don't know if it was Kernighan or Ritchie who wrote that, but I'm
fairly sure it was one or the other.

--

"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton

Mon, 29 Mar 2004 13:43:25 GMT

Quote:

> I had a chat with the team leader I mentioned previously. I told him I
> had discovered a counterargument to his casting of malloc(), and he
> replied:

> "Being able to be sure of the element size is not enough. You also need
> to know the number of the elements. For example, you might want to
> allocate 10 foo_t's to variable a and 15 bar_t's to variable b. If you
> do not cast malloc(), there is a possibility that you are allocating
> a's elements to b and b's elements to a.

If you don't bury a toad under the old oak tree at midnight, there is a
possibility that your compiler will generate a one-bit error in your
object code, without a diagnostic.

Quote:
> "Using p=malloc(10*sizeof(*p)) will not help because it's a problem
> with the 10, not with the sizeof(*p). So we need casts to make the
> compiler complain if we allocate foo_t's to a bar_t * or vice versa."

The casts don't help here. When you think about it, you will realise
that doing this:

p = (foo_t *)malloc(10 * sizeof(foo_t));

cannot magically transform a 10 into a 15 if 15 was intended. Nor can p
= malloc(10 * sizeof *p), of course, but then it doesn't claim to.

The argument is spurious and flawed, as was his previous argument.

Quote:
> Once again, I could not find a counterargument. What do you C gurus

I suggest you cut out the middle man, and bring your glorious leader to
comp.lang.c. :-)

--

"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton

Mon, 29 Mar 2004 13:50:03 GMT

 Page 1 of 2 [ 23 post ] Go to page: [1] [2]

Relevant Pages