[转载]gcc knows about malloc()

来源:互联网 发布:非结构化数据如何处理 编辑:程序博客网 时间:2024/06/10 16:24
原文地址:http://bytes.com/topic/c/answers/500390-gcc-knows-about-malloc

我只是把原信件的地址写到了下面,所有的回复没有粘贴过来。有兴趣的话,请阅读原文。

James Dow Allen
Guest
 
Posts: n/a
#1: Jun 12 '06
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

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 , 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 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.''

- - - - - - - - - - -

原创粉丝点击