gcc知道malloc() [英] gcc knows about malloc()

查看:77
本文介绍了gcc知道malloc()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

gcc编译器特别对待malloc()!我没有特别的问题,但是听到

知道gcc特殊行为的人可能会很有趣。


有些人可能觉得这篇文章很有意思;有些人可能会发现它无关紧要或令人困惑。最后的免责声明。


代码示例几乎是最小的b
演示。它们*与任何

实际应用程序代码无关。


(1)

gcc假定malloc()'对于另一个指针,返回值不是

别名。这可以通过编译

并运行以下代码两次来确认,一次使用

-Dgetnode = malloc

选项。 (如果将
getnode声明为静态,或者省略''-O''选项,则不会观察到特殊行为。)


编译并运行以下代码,首先是

gcc -Wall -O

然后用

gcc -Wall -O -Dgetnode = malloc


===开始示例代码

#include< stdio.h>


struct node {

struct node * next;

} A [10];


void * getnode(int x)

{

返回& A [x];

}


/ *将A [x]插入第3个列表插槽* /

void insert(x)

{

struct node * newp;

struct node * head = A;


newp = getnode(x);

newp-> next = head-> next-> next;

/ *编译器会重新计算head-> next,还是使用旧值? * /

head-> next-> next = newp;

}


int main(int argc,char ** argv)

{

/ *创建循环列表0 - > 1 - > 2 - > 3 - > 0 * /

A-> next = A;

insert(1);

insert(3);

insert(2);

printf("列表中的第三个元素是A [%d] \ n",A-> next-> next - A);


/ *接下来将损坏列表,但应该是确定性的! * /

insert(0);

printf(列表中的第三个元素是A [%d] \ n,A-> next->下一个 - A);

返回0;

}

===结束示例代码


(2)

说到malloc(),当编码器忽略包含< stdlib.h>时,有时会在

中给出一个误导性答案,然后

尝试输入malloc()。


虽然省略系统头文件是一个错误,严格说来是

结果问题不是由于错误地施放

malloc()函数引起的,而是由于未能完全抛出它!


在诸如

foo =(void *)malloc(TWELVE_MILLION);

是malloc'的*返回值*是cast,而不是malloc()本身。

这是另一种情况,其中C语法在

表达式与声明中具有不同的效果。


避免此问题(假设< stdlib .h>文件已经

意外删除,但有人知道malloc的正确声明)

可以写:

void * malloc();

...

foo = malloc(TWELVE_MILLION);


甚至(如果您的雇主为了明确声明而停靠您的工资

库函数):


if(0)malloc(); / *告诉gcc malloc是一个函数* /

foo =((void *(*)())malloc)(TWELVE_MILLION);


(请原谅宣告malloc是一个函数的特殊方式!

这似乎是最小可编译示例的方法!)


请不要我指责我鼓励变态(!),但有些事先讨论* b $ b *误导。


(3)

在玩游戏时,我发现了更多关于malloc()的
gcc(GNU C版本3.2)的奇怪行为。


编译以下代码,例如与

gcc -c


===开始示例代码

struct foo {int x; };


int main(int argc,char ** argv)

{

if(0)malloc(); / *告诉gcc malloc()是一个函数* /

return(((struct foo(*)())malloc)(sizeof(struct foo)))。x;

}

===结束示例代码


当我编译它时,我得到分段错误!

在燃烧之前,请注意:

我从未想过*运行*这个奇怪的错误程序;

分段错误在编辑过程中发生。


免责声明:


(a)没有人提倡错误的打字或错误

替换malloc()。


(b)没有人声称''gcc''有缺陷。相反,

sample(1)演示了由于malloc()的语义,gcc能够应用
的聪明效率。 ((3)中的错误,我想,

很容易避免,FSF可能会知道它。)


(c)这篇文章可能是偏离主题的,因为gcc不是标准的C,

和一些读者使用其他编译器。但这是一个一般的论坛

与C有关的问题。


(顺便说一下,为什么*不是每个人都使用gcc编译器?)


(d)标准C规定了编译器*可能*做什么以及它必须*做什么,而不是它* *可能*做什么。不过,我想知道标准

是否特别容忍gcc在(1)中的优化。


(e)以上两个代码样本都违反了*标准C的规则,

而不是有缺陷的优化或分段错误,

]> ......符合标准的C编译器是合适的

]>垃圾[我的]硬盘,或发动核打击....

这样的评论很有趣,但确实变得重复。

坦率地说,任何没有兴趣的人在上面的C片段

之外,观察到它们是不合规的,因为缺乏想象力而打击了我b $ b。


代码样本(1)很容易生成标准C

代码,其中有趣的差异来自于测量或检查目标代码的时间,但似乎更多

直接展示gcc的聪明优化

,取代malloc()使优化无效。

James Dow Allen


- - - - - - - - - -


告诉我们,参议员,你对酒精有什么看法?


``好吧,如果用酒精你就意味着那种带来笑声的酣畅淋漓的精神



生活在社交聚会上,这会润滑各种各样的齿轮。 b $ b业务

交易,让生活的艰辛更容易承受,然后我说

欢呼它,我支持它的合法销售和消费。


``但是,如果用酗酒你的意思就是那种剥夺了b $ b b


预算的邪恶精华,这是对身体和心灵的毒素,这会导致男人



互相攻击并且在他们的职业中失败,然后我说'

on

it ,我会竭尽全力阻止它的销售和消费。$'$

- - - - - - - - - - -

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

- - - - - - - - - - -

推荐答案



James Dow Allen写道:

James Dow Allen wrote:

说到malloc(),当编码器忽略包含< stdlib.h>然后
尝试输入malloc()时,有时会给出一个误导性的答案。
省略系统头文件是一个错误,严格说出结果蚂蚁问题不是由于错误地转换了malloc()函数引起的,而是由于没有完全抛出它!


不,产生的问题是由于未能包含标题引起的。

在表达式中如
foo =(void *)malloc (TWELVE_MILLION);
是malloc'的*返回值*是cast,而不是malloc()本身。


编号如果没有事先正确的声明,那就是

整数返回值被放置的位置。这可能是也可能不是
是malloc()返回其值的位置。它显然是不是malloc()

本身虽然 - 这甚至意味着什么?

这是另一种情况,其中C语法在
表达式与声明中具有不同的效果。


你是什么意思?

为了避免这个问题(假设< stdlib.h>文件被意外删除了,但是一个知道malloc的正确声明)
可以写:
void * malloc();
...
foo = malloc(TWELVE_MILLION);


如果这恰好是您实现中的正确声明,

虽然在任何现代实现中都不太可能出现这种情况。

甚至(如果您的雇主为了明确宣布库函数而停靠您的工资):

if(0)malloc(); / *告诉gcc malloc是一个函数* /
foo =((void *(*)())malloc)(TWELVE_MILLION);

(请原谅声明的那种特殊方式malloc是一个函数!


你没有在这里声明malloc是一个函数。

这似乎是一个最小可编译示例的方法;)


正确的方法是包括适当的标题。

请不要指责我鼓励变态(!),但有些
先前的讨论*是误导性的。

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 resultant problems are caused by failing to include the header.
In an expression such as
foo = (void *)malloc(TWELVE_MILLION);
it is malloc''s *return value* that is cast, not malloc() itself.
No. Without a prior correct declaration, it''s the location in which
integer return values get placed which gets cast. This may or may not
be where malloc() returns its value. It''s obviously "not malloc()
itself" though - what does that even mean?
This is another case where C syntax has different effect in
expression vs declaration.
What do you mean?
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);
If that happens to be the correct declaration in your implementation,
though it''s unlikely to be the case in any modern implementation.
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!
You don''t declare that malloc is a function anywhere here.
It seemed like an approach for "minimum compilable example"!)
The correct approach would be to include the appropriate header.
Please don''t accuse me of encouraging perversion (!), but some
prior discussions *were* misleading.




可能,但不会像上面写的那些非凡的东西那样具有误导性。



Possibly, but nowhere near as misleading as the remarkable stuff you
wrote above.


2006年6月12日00:57:37 -0700,在comp.lang.c中,James Dow Allen

< jd ********* @ yahoo.com>写道:
On 12 Jun 2006 00:57:37 -0700, in comp.lang.c , "James Dow Allen"
<jd*********@yahoo.com> wrote:
说到malloc(),当编码器忽略包括< stdlib.h>,然后尝试使用类型转换malloc()。

虽然省略系统头文件是一个错误,严格说来产生的问题不是由于施放造成的。
malloc()函数不正确,但是根本没有投出它!


编号如果省略标题,编译器必须假设malloc返回

int。认为将int转换为指针是一个常见错误

fixes这个。不是这样。作为一个微不足道的反例,一些真实世界的操作系统使用不同的指针和整数寄存器,

并在整数寄存器中输入垃圾不会有帮助。 br />
在一个表达式中,例如
foo =(void *)malloc(TWELVE_MILLION);
是malloc'的*返回值*是cast,而不是malloc()本身。


当然,但是一旦编译完成,malloc()就是一堆机器

语言指令,那么施放它会毫无意义! />
这是另一种情况,其中C语法在
表达式与声明中具有不同的效果。


这没有任何意义 - 你是什么意思?

为了避免这个问题(假设< stdlib.h>文件已被删除
意外删除了,但有人知道malloc的正确声明)
可以写:
void * malloc();


这是由标准保证的,第7.1.4节

if(0)malloc(); / *告诉gcc malloc是一个函数* /
foo =((void *(*)())malloc)(TWELVE_MILLION);


这是不保证的,是非常糟糕的做法,并导致

未定义的行为。在许多实现中,这样的代码会导致在运行时出现无法解释的原因。
请不要指责我鼓励变态(!),但有些
之前的讨论*具有误导性。


我认为你有一些误解,可能只是基于''友好'硬件上的

体验。

玩游戏时在周围,我发现了更多关于malloc()的gcc(GNU C版本3.2)的离奇行为。


这是offtopic,你需要把c bug带到gcc新闻组

和论坛。

当我编译它时,我得到分段错误!


所以你发现了一个编译器错误 - 请通过他们通常的

方法向gcc报告。

(c)这篇文章可能是偏离主题的,因为gcc不是标准的C,
和一些读者使用其他编译器。但这是一个关于C.


相关问题的一般论坛。请阅读欢迎信息,以及大量的消息

讨论话题

(顺便说一句,为什么*不是每个人都使用gcc编译器?)
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. If you omit the header, the compiler must assume malloc returns an
int. It is a common mistake to think that casting the int to a pointer
"fixes" this. Not so. As a trivial counterexample, some real-world
operating systems use different registers for pointers and integers,
and casting the garbage in the integer register won''t help.
In an expression such as
foo = (void *)malloc(TWELVE_MILLION);
it is malloc''s *return value* that is cast, not malloc() itself.
Of course, but then once compiled, malloc() is a bunch of machine
language instructions, it would be fairly meaningless to cast that !
This is another case where C syntax has different effect in
expression vs declaration.
This doesn''t make any sense - what do you mean?
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();
This is guaranteed by the Standard, section 7.1.4
if (0) malloc(); /* tell gcc that malloc is a function */
foo = ((void *(*)())malloc)(TWELVE_MILLION);
this is NOT guaranteed, is exceptionally bad practice, and leads to
undefined behaviour. On many implementations, such code would lead to
unexplained crashes at runtime.
Please don''t accuse me of encouraging perversion (!), but some
prior discussions *were* misleading.
I think you have some misunderstandings, probably based on only
experience on ''friendly'' hardware.
While playing around, I discovered more bizarre behavior by
gcc (GNU C version 3.2) concerning malloc().
This is offtopic here, you need to take C bugs to the gcc newsgroups
and fora.
When I compile it, I get "Segmentation fault"!
so you found a compiler bug - please report it to gcc via their usual
method.
(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.
Please read the Welcome message, and about a zillion messages
discussion topicality
(BTW, why *doesn''t* everyone use the gcc compiler?)




因为鱼没有脚。


-

马克麦金太尔


调试是第一次编写代码的两倍。

因此,如果您尽可能巧妙地编写代码,那么根据定义,您可能不够聪明,无法对其进行调试。

--Brian Kernighan



Because fish don''t have feet.

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


Mark McIntyre< ma ********** @ spamcop.net>写道:
Mark McIntyre <ma**********@spamcop.net> wrote:
2006年6月12日00:57:37 -0700,在comp.lang.c,James Dow Allen
< jd ******** *@yahoo.com>写道:
On 12 Jun 2006 00:57:37 -0700, in comp.lang.c , "James Dow Allen"
<jd*********@yahoo.com> wrote:
if(0)malloc(); / *告诉gcc malloc是一个函数* /
foo =((void *(*)())malloc)(TWELVE_MILLION);
if (0) malloc(); /* tell gcc that malloc is a function */
foo = ((void *(*)())malloc)(TWELVE_MILLION);



这不保证,是非常糟糕的做法,并导致未定义的行为。在许多实现中,这样的代码会导致在运行时出现无法解释的崩溃。



this is NOT guaranteed, is exceptionally bad practice, and leads to
undefined behaviour. On many implementations, such code would lead to
unexplained crashes at runtime.




哪里有未定义的行为?代码未执行且包含

没有语法错误不会导致未定义的行为。所有函数指针

类型应该具有相同的表示。目前尚不清楚

这里有什么不确定的。



Where''s the undefinedd behavior? Code that''s not executed and contains
no syntax errors doesn''t cause undefined behavior. All function pointer
types are supposed to have the same representation. It''s not clear
what''s undefined here.


这篇关于gcc知道malloc()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆