gpt4 book ai didi

c - gcc、严格别名和恐怖故事

转载 作者:太空狗 更新时间:2023-10-29 16:18:43 26 4
gpt4 key购买 nike

<分区>

gcc-strict-aliasing-and-casting-through-a-union我问是否有人遇到过通过指针进行 union 双关的问题。到目前为止,答案似乎是

这个问题的范围更广:您有关于 gcc 和严格别名的任何恐怖故事吗?

背景:引自AndreyT's answer in c99-strict-aliasing-rules-in-c-gcc :

"Strict aliasing rules are rooted in parts of the standard that were present in C and C++ since the beginning of [standardized] times. The clause that prohibits accessing object of one type through a lvalue of another type is present in C89/90 (6.3) as well as in C++98 (3.10/15). ... It is just that not all compilers wanted (or dared) to enforce it or rely on it."

好吧,gcc 现在敢于这样做,它有 -fstrict-aliasing 开关。这导致了一些问题。例如,参见优秀文章 http://davmac.wordpress.com/2009/10/关于一个 Mysql 错误,以及 http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html 中同样出色的讨论.

其他一些不太相关的链接:

那么重复一遍,你有自己的恐怖故事吗? -Wstrict-aliasing 指示的问题当然是首选。也欢迎其他 C 编译器。

6 月 2 日添加:Michael Burr's answer 中的第一个链接,确实可以算作恐怖故事,但可能有点过时(自 2003 年起)。我做了一个快速测试,但问题显然已经消失了。

来源:

#include <string.h>
struct iw_event { /* dummy! */
int len;
};
char *iwe_stream_add_event(
char *stream, /* Stream of events */
char *ends, /* End of stream */
struct iw_event *iwe, /* Payload */
int event_len) /* Real size of payload */
{
/* Check if it's possible */
if ((stream + event_len) < ends) {
iwe->len = event_len;
memcpy(stream, (char *) iwe, event_len);
stream += event_len;
}
return stream;
}

具体的投诉是:

Some users have complained that when the [above] code is compiled without the -fno-strict-aliasing, the order of the write and memcpy is inverted (which means a bogus len is mem-copied into the stream).

编译代码,在 CYGWIN wih -O3 上使用 gcc 4.3.4(如果我错了,请纠正我——我的汇编程序有点生疏了!):

_iwe_stream_add_event:
pushl %ebp
movl %esp, %ebp
pushl %ebx
subl $20, %esp
movl 8(%ebp), %eax # stream --> %eax
movl 20(%ebp), %edx # event_len --> %edx
leal (%eax,%edx), %ebx # sum --> %ebx
cmpl 12(%ebp), %ebx # compare sum with ends
jae L2
movl 16(%ebp), %ecx # iwe --> %ecx
movl %edx, (%ecx) # event_len --> iwe->len (!!)
movl %edx, 8(%esp) # event_len --> stack
movl %ecx, 4(%esp) # iwe --> stack
movl %eax, (%esp) # stream --> stack
call _memcpy
movl %ebx, %eax # sum --> retval
L2:
addl $20, %esp
popl %ebx
leave
ret

对于迈克尔回答中的第二个链接,

*(unsigned short *)&a = 4;

gcc 通常(总是?)会发出警告。但我相信一个有效的解决方案(对于 gcc)是使用:

#define CAST(type, x) (((union {typeof(x) src; type dst;}*)&(x))->dst)
// ...
CAST(unsigned short, a) = 4;

我已经在 gcc-strict-aliasing-and-casting-through-a-union 中询问过这是否可以, 但到目前为止没有人不同意。

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com