More about casting malloc()...
Author |
Message |
Joona I Palast #1 / 23
|
 More about casting malloc()...
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 say about this? --
| 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 |
|
 |
karl malbra #2 / 23
|
 More about casting malloc()...
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 |
|
 |
Mike Wahle #3 / 23
|
 More about casting malloc()...
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."
Tell your 'team leader' (Ha!), to read a C textbook. This is pure nonsense. A cast *inhibits* type-related compiler 'complaints', it doesn't enable them. Have him read a C text about malloc(), noting its 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 >say about this?
I think your 'team leader' must have acquired his 'leadership' position by less than legitimate means. :-) -Mike
|
Mon, 29 Mar 2004 07:03:49 GMT |
|
 |
Tak-Shing Cha #4 / 23
|
 More about casting malloc()...
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 straightforward. OTOH, if your team leader is extremely creative 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 |
|
 |
Tak-Shing Cha #5 / 23
|
 More about casting malloc()...
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 |
|
 |
Thoma #6 / 23
|
 More about casting malloc()...
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 > say about this? > --
> | 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 |
|
 |
Lawrence Kir #7 / 23
|
 More about casting malloc()...
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 >say about this?
Neither the premises of the argument nor the conclusions drawn from them are valid. -- -----------------------------------------
-----------------------------------------
|
Mon, 29 Mar 2004 10:23:56 GMT |
|
 |
Mike Wahle #8 / 23
|
 More about casting malloc()...
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 of a byte address ===================== [these 'address boundaries' are platform-dependent] -Mike
|
Mon, 29 Mar 2004 10:17:55 GMT |
|
 |
Thoma #9 / 23
|
 More about casting malloc()...
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); instead? > 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 ;) 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 > of a byte address > ===================== > [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 |
|
 |
Daniel Dekan #10 / 23
|
 More about casting malloc()...
Quote: > [...] > Once again, I could not find a counterargument. What do you C gurus > say about this?
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 |
|
 |
Chris Tore #11 / 23
|
 More about casting malloc()...
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 |
|
 |
Dave Vandervi #12 / 23
|
 More about casting malloc()...
[The team leader says:] 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 >say about this?
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 |
|
 |
Dave Vandervi #13 / 23
|
 More about casting malloc()...
[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).]
[The team leader says:] 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 >say about this?
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 |
|
 |
Richard Heathfiel #14 / 23
|
 More about casting malloc()...
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 |
|
 |
Richard Heathfiel #15 / 23
|
 More about casting malloc()...
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 > say about this?
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] |
|