Re: gcc knows about malloc()
- From: Keith Thompson <kst-u@xxxxxxx>
- Date: Mon, 12 Jun 2006 19:23:03 GMT
"James Dow Allen" <jdallen2000@xxxxxxxxx> writes:
[...]
Speaking of malloc(), a misleading answer is sometimes given in
this ng, when coders neglect to include <stdlib.h>, and then
attempt to type-cast malloc().
While omitting the system header file is a mistake, strictly
speaking the resultant problems aren't caused by casting the
malloc() function incorrectly, but by failing to cast it at all!
No, the undefined behavior is caused by calling malloc() without a
visible prototype. Casting the result may change the way that
undefined behavior is manifested, and may prevent the compiler from
warning you about it.
In an expression such as
foo = (void *)malloc(TWELVE_MILLION);
it is malloc's *return value* that is cast, not malloc() itself.
Of course.
This is another case where C syntax has different effect in
expression vs declaration.
I'll join several other people in not understanding what you mean by
this. If you're drawing a parallel between
(void*)malloc(TWELVE_MILLION)
and
void *malloc(size_t size);
that's not the same syntax.
This is a case where one piece of C syntax in an expression has a
different effect than a different piece of C syntax in a declaration.
To avoid the problem (assuming the <stdlib.h> file has been
accidentally erased, but one knows malloc's correct declaration)
one could write:
void *malloc();
...
foo = malloc(TWELVE_MILLION);
One could, but one would very likely invoke undefined behavior.
Given
void *malloc();
the compiler doesn't know the type, or even number, of malloc()'s
argument(s). Unless TWELVE_MILLION happens to be promoted to
a type compatible with size_t, you're lying to the compiler.
Or even (if your employer docks your pay for explicitly declaring
library functions) :
if (0) malloc(); /* tell gcc that malloc is a function */
foo = ((void *(*)())malloc)(TWELVE_MILLION);
Undefined behavior.
By converting malloc (a function name which has been implicitly
converted to a pointer-to-function) to type (void *(*)(), you're
trying to avoid the problem with malloc()'s return type, but you're
still lying to the compiler. The compiler assumes that malloc() is a
function returning int. You're *assuming* that this is the case (it
isn't), and converting the bogus pointer to a pointer to function
returning void*. It's the same problem you get with the simpler
(void*)malloc(TWELVE_MILLION)
where you take something that's really a void*, forcing the compiler
to assume it's an int, and converting it from int to void*.
You're probably assuming that all pointer-to-function types have the
same representation. That's probably true in most or all
implementations, but it's not guaranteed. The standard guarantees
that any pointer-to-function type can be converted to any other
pointer-to-function type and back again, yielding the original pointer
value -- but the conversions don't necessarily just reinterpret the
bits of the pointer. C99 6.2.5 specifically guarantees that all
pointers to structure types have the same representation and alignment
requirements; likewise for pointers to union types. It makes no such
guarantess for pointers to function types.
In all your function declarations and casts, you're omitting the
parameter type. If you must provide your own declaration of malloc()
for some reason, the correct declaration is
void *malloc(size_t);
or
void *malloc(size_t size);
There is, of course, no good reason to use any method other than
#include <stdlib.h>
(unless your compilation system is broken and you're unable to repair
or replace it -- but if it's that badly broken it's not clear that
even a correct declaration will be an effective workaround).
[snip]
Please don't accuse me of encouraging perversion (!), but some
prior discussions *were* misleading.
Some of them undoubtedly were, but not all of them. I think you've
just misunderstood them.
[...]
When I compile it, I get "Segmentation fault"![...]
Before flaming, please note:
It never occurred to me to *run* this bizarre faulty program;
the "Segmentation fault" occurs during compilation.
(b) No one is claiming 'gcc' is defective. To the contrary,
sample (1) demonstrates a clever efficiency that gcc is able to
apply due to malloc()'s semantics. (The fault in (3), I imagine,
would be easy to avoid and FSF probably would if it knew of it.)
<OT>
If gcc gets a segmentation fault during compilation, regardless of how
bad the compiled code might be, of course it's defective. In other
words, you've found a bug. You should report it to the gcc
maintainers. See <http://gcc.gnu.org/> for information on how to do
this.
</OT>
(BTW, why *doesn't* everyone use the gcc compiler?)
On some platforms, gcc doesn't exist. On others, another compiler
generates better code. For those who need C99, there are compilers
that support it better than gcc does. Many C compilers have features
that gcc lacks. I'm sure there are other reasons.
Why *should* everyone use the same compiler? The point of a standard
is that it's a contract between the implementer and the programmer; if
I write conforming code, I can use any conforming compiler I like.
--
Keith Thompson (The_Other_Keith) kst-u@xxxxxxx <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
.
- Follow-Ups:
- Re: gcc knows about malloc()
- From: Jordan Abel
- Re: gcc knows about malloc()
- References:
- gcc knows about malloc()
- From: James Dow Allen
- gcc knows about malloc()
- Prev by Date: Re: getchar() after EOF
- Next by Date: struct in C99
- Previous by thread: Re: [OT] gcc knows about malloc()
- Next by thread: Re: gcc knows about malloc()
- Index(es):
Relevant Pages
|