473,396 Members | 2,009 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

gcc knows about malloc()

The gcc compiler treats malloc() specially! I have no
particular question, but it might be fun to hear from
anyone who knows about gcc's special behavior.

Some may find this post interesting; some may find it
off-topic or confusing. Disclaimers at end.

The code samples are intended to be nearly minimal
demonstrations. They are *not* related to any
actual application code.

(1)
gcc assumes that malloc()'s return value is not an
alias for another pointer. This can be confirmed by compiling
and running the following code twice, once with a
-Dgetnode=malloc
option. (The special behavior will not be observed if
getnode is declared static, or the '-O' option is omitted.)

Compile and run the following code, first with
gcc -Wall -O
then with
gcc -Wall -O -Dgetnode=malloc

=== Begin sample code
#include <stdio.h>

struct node {
struct node *next;
} A[10];

void *getnode(int x)
{
return &A[x];
}

/* Insert A[x] into 3rd list slot */
void insert(x)
{
struct node *newp;
struct node *head = A;

newp = getnode(x);
newp->next = head->next->next;
/* will compiler recompute head->next, or use old value? */
head->next->next = newp;
}

int main(int argc, char **argv)
{
/* Create a circular list 0 -> 1 -> 2 -> 3 -> 0 */
A->next = A;
insert(1);
insert(3);
insert(2);
printf("Third element in list is A[%d]\n", A->next->next - A);

/* Next will "damage" the list, but should be deterministic! */
insert(0);
printf("Third element in list is A[%d]\n", A->next->next - A);
return 0;
}
=== End sample code

(2)
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!

In an expression such as
foo = (void *)malloc(TWELVE_MILLION);
it is malloc's *return value* that is cast, not malloc() itself.
This is another case where C syntax has different effect in
expression vs 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);

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);

(Please forgive the peculiar way to declare that malloc is a function!
It seemed like an approach for "minimum compilable example"!)

Please don't accuse me of encouraging perversion (!), but some
prior discussions *were* misleading.

(3)
While playing around, I discovered more bizarre behavior by
gcc (GNU C version 3.2) concerning malloc().

Compile the following code, e.g. with
gcc -c

=== Begin sample code
struct foo { int x; };

int main(int argc, char **argv)
{
if (0) malloc(); /* tell gcc malloc() is a function */
return (((struct foo(*)())malloc)(sizeof(struct foo))).x;
}
=== End sample code

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.

Disclaimers:

(a) No one is advocating faulty type-casting, or faulty
replacements for malloc().

(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.)

(c) This post may be off-topic because gcc isn't standard C,
and some readers use other compilers. But this is a general forum
for issues relating to C.

(BTW, why *doesn't* everyone use the gcc compiler?)

(d) Standard C specifies what a compiler *may* do and what it
*must* do, not what it *might* do. Still, I wonder if the Standard
specifically condones gcc's optimization in (1).

(e) Both code samples above *violate* the rules of Standard C,
and instead of the "faulty" optimization or Segmentation fault,
]> ... it would be proper for a compliant Standard C compiler
]> to trash [my] hard disk, or launch a nuclear strike....
Such comments are amusing, but do become repetitious.
Frankly, anyone who has no interest in the above C fragments
beyond observing that they are non-compliant, strikes me
as lacking imagination.

For code sample (1) it would be easy to produce Standard C
code where the interesting difference emerges from a timing
measurement or examining object code, but it seemed more
straightforward to demonstrate gcc's clever optimization
with a substituted malloc() that invalidates the optimization.
James Dow Allen

- - - - - - - - - - -

Tell us, Senator, what is your opinion of alcohol?

``Well, if by alcohol you mean that hearty spirit which brings laughter
and
livelihood to social gatherings, which lubricates the gears of
business
transactions, which makes life's hardships easier to bear, then I say
hurrah for it, and I support its legal sale and consumption.

``However, if by alcohol you mean that evil essence which robs the
family
budget, which is a toxin to the body and the mind, which causes men
to
assault one another and to fail in their professions, then I say fie
on
it, and I will work with all my power to prevent its sale and
consumption.''

- - - - - - - - - - -

Jun 12 '06
68 15604
In article <4f*************@individual.net>,
Jordan Abel <ra*******@gmail.com> wrote:
Ian Collins <ia******@hotmail.com> wrote:
There's at least as many 64bit desktop system shipping these days as
there are 32bit,


That, i'd doubt.


Datum: I've been going to local beige-box stores looking for pricing
on new low-end systems to replace my aging desktop. Every quote I've
gotten so far has included a 64-bit processor.
dave

--
Dave Vandervies dj******@csclub.uwaterloo.ca
Next time, mark subtleties more clearly. Such as with a <subtlety> tag.
So that idiots like me will also be able to spot them.
--Joona I Palaste in comp.lang.c
Jun 14 '06 #51
Keith Thompson wrote:
Consider the expression
malloc
If a correct prototype is visible, this expression (after the implicit
conversion that's done to function names in most contexts) is
void *(*)(size_t)
Casting this expression to the same type, of course, performs no
actual conversion and simply yields the same pointer-to-function
value.

But in the absence of a prototype, the compiler doesn't know the type
of the expression
malloc
so it cannot, in the general case, generate correct code to convert
this value to type void *(*)(size_t). It's likely to generate code
that would convert a value of type int (*)() to type
void *(*)(size_t); applying this code to a value that's *actually* of
type void *(*)(size_t) unleashes the nasal demons.


Seems to make sense. Is there any documentation in the
standard to back this up?

Personally I'm not convinced that the code should even
compile. In C99 it certainly doesn't: C99 does not have
implicit function declaration.

I don't have a copy of C90 to check, but I am wondering,
what is the scope of the identifier 'malloc' that is
"declared" by:

if (0) malloc();

? My copy of gcc does not compile if the line is changed to:
if (0) { malloc(); }

saying that in the next line, 'malloc' is an undeclared symbol.
This which would be the only case I've ever heard of where
adding braces around STMT in

if (x) STMT;

makes a difference to anything, and also the first case where
identifiers declared in the block of a control statement can
"leak" to outside the control statement.

My copy of GCC also permits:

sizeof( foo() );

as "declaring" foo; it now seems difficult to argue that

sizeof( 1/0 );

should be permitted, as we were discussing in another thread.

Jun 14 '06 #52
Old Wolf wrote:
Keith Thompson wrote:
Consider the expression
malloc
If a correct prototype is visible, this expression (after the implicit
conversion that's done to function names in most contexts) is
void *(*)(size_t)
Casting this expression to the same type, of course, performs no
actual conversion and simply yields the same pointer-to-function
value.

But in the absence of a prototype, the compiler doesn't know the type
of the expression
malloc
so it cannot, in the general case, generate correct code to convert
this value to type void *(*)(size_t). It's likely to generate code
that would convert a value of type int (*)() to type
void *(*)(size_t); applying this code to a value that's *actually* of
type void *(*)(size_t) unleashes the nasal demons.
Seems to make sense. Is there any documentation in the
standard to back this up?


I don't know about C89, but from C99:

7.1.3:
All identifiers with external linkage in any of the following
subclauses (including the
future library directions) are always reserved for use as identifiers
with external
linkage.
[...]
No other identifiers are reserved. If the program *declares or*
defines an identifier in a
context in which it is reserved (other than as allowed by 7.1.4), or
defines a reserved
identifier as a macro name, the behavior is undefined. (emphasis
mine)

Does C89 have similar wording? If you want, you could argue that 7.1.4
is poorly worded, though.
Personally I'm not convinced that the code should even
compile. In C99 it certainly doesn't: C99 does not have
implicit function declaration.

I don't have a copy of C90 to check, but I am wondering,
what is the scope of the identifier 'malloc' that is
"declared" by:

if (0) malloc();

? My copy of gcc does not compile if the line is changed to:
if (0) { malloc(); }

saying that in the next line, 'malloc' is an undeclared symbol.
This which would be the only case I've ever heard of where
adding braces around STMT in

if (x) STMT;

makes a difference to anything, and also the first case where
identifiers declared in the block of a control statement can
"leak" to outside the control statement.
Try
int main(void) {
if(0) (enum { zero }) 0;
return zero;
}

There is an implicit block for if-statements in C99, so adding braces
won't make a difference. My compiler rejects this code in C99 mode, but
accepts it in C89 mode, so I'm assuming that this is a C99 change.
My copy of GCC also permits:

sizeof( foo() );

as "declaring" foo; it now seems difficult to argue that

sizeof( 1/0 );

should be permitted, as we were discussing in another thread.


Why is this the same thing? If 1/0 is not evaluated, there is no
undefined behaviour. However, a declaration doesn't need evaluation to
have effect.

Jun 14 '06 #53
On Tue, 13 Jun 2006 20:16:03 +1200, Ian Collins <ia******@hotmail.com>
wrote:
jaysome wrote:
On Tue, 13 Jun 2006 19:22:15 +1200, Ian Collins <ia******@hotmail.com>
wrote:

jaysome wrote:

On Mon, 12 Jun 2006 21:04:26 GMT, Keith Thompson <ks***@mib.org>
wrote:(On some systems, where int and void* happen to be the same size, and

^^^^^^^^^^^^
that should be "nearly all systems", by my accounts.
Not realy, less than half of mine (most being 64 bit).

I don't doubt you, but you're only one in a thousand, if not a
million. What do you think about that assertion?

There's at least as many 64bit desktop system shipping these days as
there are 32bit, not including the server space which has even greater
bias to 64bit.


But a large percentage of those 64-bit desktop systems are running
32-bit code in which int and void* have the same size. I'm running
Windows XP on an AMD 64-bit dual-core processor. All of my
applications are compiled with 32-bit int and 32-bit void*.

A lot depends on what OS and compiler one is using. There are a great
many OS/compiler combinations in which int and void* are both 32 bits
on a 64-bit processor.

That said, I couldn't put up with someone who insisted that int and
void* have the same size. Such a person would be out the door on my
account.

--
jay
Jun 14 '06 #54
dj******@caffeine.csclub.uwaterloo.ca (Dave Vandervies) wrote:
In article <4f*************@individual.net>,
Jordan Abel <ra*******@gmail.com> wrote:
Ian Collins <ia******@hotmail.com> wrote:
There's at least as many 64bit desktop system shipping these days as
there are 32bit,


That, i'd doubt.


Datum: I've been going to local beige-box stores looking for pricing
on new low-end systems to replace my aging desktop. Every quote I've
gotten so far has included a 64-bit processor.


And every single one of them will have a 32-bit time_t. Right?

Sometimes I despair of us humans, I really do.

Richard
Jun 14 '06 #55

Jordan Abel wrote:
SuperKoko <ta*******@yahoo.fr> wrote:
The original pointer is int(*)()... Nowhere in your code does appear an
explicit conversion from void*(*)() to int(*)().... You just have a
buggy mean to get a int(*)() pointer from nowhere sensible (from a
symbol which should refer to an int() function but that you interpret
as a void*() function).
But that's not what your cite says. The standard may say so elsewhere,
but it doesn't say it in what you quoted.


I wrote: 3.3.4 (Cast operators)
"
A pointer to a function of one type may be converted to a pointer to a
function of another type and back again; the result shall compare equal
to the original pointer. If a converted pointer is used to call a
function that has a type that is not compatible with the type of the
called function, the behavior is undefined.
"

It seems pretty clear to me. Here, the type of the function is int().
Note that, in the context of this paragraph, convert means : Use a cast
operator (it is in the chapter on type casts).

Things are quite simple :
Either your first UB (declaring malloc with an incorrect prototype)
happens to do bad things such as a crash, in that case your program is
bad or crashes.
Or, the first UB happens to be well-defined by the compiler and results
in a valid int() function. In that case a pointer int(*)() pointing to
that function, is valid, and you can use it, and it points to a int()
function... But converting it to void*(*)() and using this new pointer
has UB except, once again, that your compiler document this UB too.
But, the compiler will have either to document the two UB separately,
or to document the combination of the two UB : i.e., it might say that
it is allowed to declare incorrectly a function and that taking the
address of the function yields a pointer which points to the correct
function (i.e., as if the declaration was correct).

But you can't assume that "knowing that the first UB doesn't behave
incorrectly" is sufficient to avoid the second UB. You must read the
compiler's documentation to know how and why, the first UB doesn't
behave incorrectly.

Jun 14 '06 #56

Erik Trulsson wrote:
James Dow Allen <jd*********@yahoo.com> wrote:
Morris Dovey wrote:
James Dow Allen wrote:
| The gcc compiler treats malloc() specially!

You seem surprised. Gcc implementations can sometimes be enhanced to
take advantage of target processor architectural features.

Note that the optimization in question has nothing to do with any
details of
either processor architecture or malloc implementation.
GCC knows about and has special handling for a large number of standard C functions
(as well as a smaller number of functions that are not part of Standard C.)
I didn't review gcc source, but did do a "strings" on the compiler
object code.
Several standard function names appeared together, but malloc appeared
a second time later, almost by itself.
Which functions it knows about is documented in the GCC manual (search for
'built-in functions'.) (GCC manuals can be found at http://gcc.gnu.org/onlinedocs/ )


I tried this, and, searching for "built-in functions" got a list of ...
(surprise!)
built-in functions. malloc is not built-in. Gnu has its own malloc()
implementation,
and mention of it shows up in other searches, but that isn't what I'm
looking for
either.

I've concluded that readers in c.l.c, if any, who know of the
optimization, or
even understood what it is, were too distracted by my peculiar casting
of
malloc to attend to the interesting issue. (I thought context made it
clear that
the peculiar casting was simply for humor, but it now seems doubtful
anyone here shares my sense of humor.)

James

Jun 14 '06 #57
Old Wolf wrote:
Keith Thompson wrote:
Consider the expression
malloc
If a correct prototype is visible, this expression (after the implicit
conversion that's done to function names in most contexts) is
void *(*)(size_t)
Casting this expression to the same type, of course, performs no
actual conversion and simply yields the same pointer-to-function
value.

But in the absence of a prototype, the compiler doesn't know the type
of the expression
malloc
so it cannot, in the general case, generate correct code to convert
this value to type void *(*)(size_t). It's likely to generate code
that would convert a value of type int (*)() to type
void *(*)(size_t); applying this code to a value that's *actually* of
type void *(*)(size_t) unleashes the nasal demons.

Seems to make sense. Is there any documentation in the
standard to back this up?

Personally I'm not convinced that the code should even
compile. In C99 it certainly doesn't: C99 does not have
implicit function declaration.


Keith's argument can also be illustrated with

#include <stddef.h>
long malloc(const char*, double, struct foo*);
void * (*pseudo_malloc)(size_t) = malloc;

.... which does not rely on implicit int.

After some pondering, I think Keith is right. His
argument is really the same as that for other kinds of
type mismatches, like

/* file1.c */
double trouble;

/* file2.c */
extern int trouble;
...
double toil = (double)trouble;

Even though the compiler of file2.c is told to convert the
value of `trouble' to the type of `trouble's definition, it's
been misinformed about the "starting point" for the conversion
and (probably) generates incorrect code.

--
Eric Sosman
es*****@acm-dot-org.invalid
Jun 14 '06 #58
Eric Sosman wrote:
Old Wolf wrote:
Keith Thompson wrote:
Consider the expression
malloc
If a correct prototype is visible, this expression (after the implicit
conversion that's done to function names in most contexts) is
void *(*)(size_t)
Casting this expression to the same type, of course, performs no
actual conversion and simply yields the same pointer-to-function
value.

But in the absence of a prototype, the compiler doesn't know the type
of the expression
malloc
so it cannot, in the general case, generate correct code to convert
this value to type void *(*)(size_t). It's likely to generate code
that would convert a value of type int (*)() to type
void *(*)(size_t); applying this code to a value that's *actually* of
type void *(*)(size_t) unleashes the nasal demons.

Seems to make sense. Is there any documentation in the
standard to back this up?

Personally I'm not convinced that the code should even
compile. In C99 it certainly doesn't: C99 does not have
implicit function declaration.


Keith's argument can also be illustrated with

#include <stddef.h>
long malloc(const char*, double, struct foo*);
void * (*pseudo_malloc)(size_t) = malloc;


Adding the required cast, and making one implicit conversion explicit:

long malloc(const char*, double, struct foo*);
void * (*pseudo_malloc)(size_t) = (void *(*)(size_t)) &malloc;
... which does not rely on implicit int.

After some pondering, I think Keith is right. His
argument is really the same as that for other kinds of
type mismatches, like

/* file1.c */
double trouble;

/* file2.c */
extern int trouble;
...
double toil = (double)trouble;
It's closer to double *toil = (double *) &trouble;.
Even though the compiler of file2.c is told to convert the
value of `trouble' to the type of `trouble's definition, it's
been misinformed about the "starting point" for the conversion
and (probably) generates incorrect code.


I don't think it's valid, but I don't think it's as likely to blow up
as you seem to either.

Jun 14 '06 #59
On 2006-06-14, Richard Bos <rl*@hoekstra-uitgeverij.nl> wrote:
dj******@caffeine.csclub.uwaterloo.ca (Dave Vandervies) wrote:
In article <4f*************@individual.net>,
Jordan Abel <ra*******@gmail.com> wrote:
>Ian Collins <ia******@hotmail.com> wrote:
>> There's at least as many 64bit desktop system shipping these days as
>> there are 32bit,
>
>That, i'd doubt.


Datum: I've been going to local beige-box stores looking for pricing
on new low-end systems to replace my aging desktop. Every quote I've
gotten so far has included a 64-bit processor.


And every single one of them will have a 32-bit time_t. Right?

Sometimes I despair of us humans, I really do.

Well, when the terminator happens, we'll just have to wait until
2038, and then they'll reset to 1970 and start only killing hippies.

So it's not all bad. ;-)

--
Andrew Poelstra < http://www.wpsoftware.net/blog >
To email me, use "apoelstra" at the above address.
I know that area of town like the back of my head.
Jun 14 '06 #60
In article <11**********************@i40g2000cwc.googlegroups .com>,
James Dow Allen <jd*********@yahoo.com> wrote:
I've concluded that readers in c.l.c, if any, who know of the
optimization, or
even understood what it is, were too distracted by my peculiar casting
of
malloc to attend to the interesting issue.


Ummm, no, the "interesting issue" was one which is well known to
many and so not worth thinking about. "gcc" and "weird and
non-standard C compilers" would appear in the same category
of most computing thesaurii . Is it a profitable use of our time
to catelogue all of gcc's oddities?
--
Is there any thing whereof it may be said, See, this is new? It hath
been already of old time, which was before us. -- Ecclesiastes
Jun 14 '06 #61

Walter Roberson wrote:
In article <11**********************@i40g2000cwc.googlegroups .com>,
James Dow Allen <jd*********@yahoo.com> wrote:
I've concluded that readers in c.l.c, if any, who know of the
optimization, or even understood what it is, were too distracted
by my peculiar casting of malloc to attend to the interesting issue.


Ummm, no, the "interesting issue" was one which is well known to
many and so not worth thinking about.


What it be rude to ask you which "interesting issue" *you* are talking
about? I erred greatly by introducing many unrelated issues in a
single post, but I've yet to see an acknowledgement that *anyone*
even *noticed* gcc's peculiar optimization demonstrated in my code
sample (1), let alone that that behavior "is well known to many."

If only gcc does this optimization, I think it's still on-topic here,
as relevant to what C compilers may or should do.

James Dow Allen

Jun 16 '06 #62
In article <11*********************@p79g2000cwp.googlegroups. com>,
James Dow Allen <jd*********@yahoo.com> wrote:

Walter Roberson wrote:
Ummm, no, the "interesting issue" was one which is well known to
many and so not worth thinking about.

What it be rude to ask you which "interesting issue" *you* are talking
about? I erred greatly by introducing many unrelated issues in a
single post, but I've yet to see an acknowledgement that *anyone*
even *noticed* gcc's peculiar optimization demonstrated in my code
sample (1), let alone that that behavior "is well known to many."
Oh, I noticed you pointing out the executation difference, and
confirmed it on a local copy of gcc, but gcc has about the same
relationship to code as university students have proverbably had to
beer: afterwards, someone has to clean up after the pranks and vomit.

If only gcc does this optimization, I think it's still on-topic here,
as relevant to what C compilers may or should do.


Hmmm, possibly. I would need to examine the sequence more carefully
to see for myself whether any constraint had been violated by the
program.
--
If you lie to the compiler, it will get its revenge. -- Henry Spencer
Jun 16 '06 #63
"James Dow Allen" <jd*********@yahoo.com> writes:
Walter Roberson wrote:
In article <11**********************@i40g2000cwc.googlegroups .com>,
James Dow Allen <jd*********@yahoo.com> wrote:
>I've concluded that readers in c.l.c, if any, who know of the
>optimization, or even understood what it is, were too distracted
>by my peculiar casting of malloc to attend to the interesting issue.


Ummm, no, the "interesting issue" was one which is well known to
many and so not worth thinking about.


What it be rude to ask you which "interesting issue" *you* are talking
about? I erred greatly by introducing many unrelated issues in a
single post, but I've yet to see an acknowledgement that *anyone*
even *noticed* gcc's peculiar optimization demonstrated in my code
sample (1), let alone that that behavior "is well known to many."

If only gcc does this optimization, I think it's still on-topic here,
as relevant to what C compilers may or should do.


Any compiler is allowed to use knowledge of functions in the standard
library. I've also seen gcc transform this:
printf("hello, world\n");
to this:
puts("hello, world");

They're both reasonably cool optimizations, but I think the fact that
they're allowed is well known, and there's really not all that much
more to say about them in the context of the C language.
(comp.compilers or one of the gnu.gcc.* newsgroups would be an
appropriate place to discuss the mechanics of how these optimizations
are done.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <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.
Jun 16 '06 #64
On 16 Jun 2006 00:20:13 -0700, in comp.lang.c , "James Dow Allen"
<jd*********@yahoo.com> wrote:
If only gcc does this optimization, I think it's still on-topic here,
as relevant to what C compilers may or should do.


I noticed this, but its not topical here since this group discusses
ISO C, not how a given compiler implements something under the hood.

If ever you find yourself looking at intermediate or assembler files.,
you need to take the discussion to a gcc group or whatever.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Jun 16 '06 #65
Mark McIntyre <ma**********@spamcop.net> writes:
On 16 Jun 2006 00:20:13 -0700, in comp.lang.c , "James Dow Allen"
<jd*********@yahoo.com> wrote:
If only gcc does this optimization, I think it's still on-topic here,
as relevant to what C compilers may or should do.


I noticed this, but its not topical here since this group discusses
ISO C, not how a given compiler implements something under the hood.

If ever you find yourself looking at intermediate or assembler files.,
you need to take the discussion to a gcc group or whatever.


The fact that compilers in general are allowed to perform this
optimization is topical. The fact that gcc in particular does so is
not (though I don't object to mentioning it in passing).

--
Keith Thompson (The_Other_Keith) ks***@mib.org <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.
Jun 16 '06 #66
On Fri, 16 Jun 2006 22:13:04 GMT, in comp.lang.c , Keith Thompson
<ks***@mib.org> wrote:
Mark McIntyre <ma**********@spamcop.net> writes:
If ever you find yourself looking at intermediate or assembler files.,
you need to take the discussion to a gcc group or whatever.
The fact that compilers in general are allowed to perform this
optimization is topical. The fact that gcc in particular does so is
not


agreed
(though I don't object to mentioning it in passing).


me neither, which is why I didn't comment on it the first time.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Jun 16 '06 #67

Keith Thompson wrote:
"James Dow Allen" <jd*********@yahoo.com> 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.


Keith, your postings keep saying prototype, but what you
mean is declaration. It's not necessary that there be a
prototype for malloc, only a declaration.
...
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,


The behavior is undefined, but that's because the identifier
malloc hasn't been declared (or because the implicit declaration
doesn't match the definition in the case of C90). There is nothing
in the conversion in and of itself that causes undefined behavior.
An implementation that gives a suitable definition for what
happens in the case of undeclared identifiers would have no
problem with undefined behavior for this code (assuming, as
noted elsewhere, that the TWELVE_MILLION argument
is such that it gets passed as a size_t).

Jun 20 '06 #68
en******@yahoo.com writes:
Keith Thompson wrote:
"James Dow Allen" <jd*********@yahoo.com> 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.


Keith, your postings keep saying prototype, but what you
mean is declaration. It's not necessary that there be a
prototype for malloc, only a declaration.


Good point.

With a visible declaration that's not a prototype (i.e., that doesn't
specify the parameter type), a call with an argument that's not of
type size_t (or a type that promotes to size_t) will still invoke
undefined behavior.
...
> 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,


The behavior is undefined, but that's because the identifier
malloc hasn't been declared (or because the implicit declaration
doesn't match the definition in the case of C90). There is nothing
in the conversion in and of itself that causes undefined behavior.


Right, and I didn't mean to imply otherwise. The cast is *intended*
to avoid the problem the problem with UB, but it doesn't.
An implementation that gives a suitable definition for what
happens in the case of undeclared identifiers would have no
problem with undefined behavior for this code (assuming, as
noted elsewhere, that the TWELVE_MILLION argument
is such that it gets passed as a size_t).


Well, an implementation is free to define the behavior of anything
that's undefined behavior according to the standard.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <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.
Jun 20 '06 #69

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

74
by: Suyog_Linux | last post by:
I wish to know how the free()function knows how much memory to be freed as we only give pointer to allocated memory as an argument to free(). Does system use an internal variable to store allocated...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development projectplanning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.