gcc-strict-aliasing-and-casting-through-a-unionで、ポインターを介したユニオンのしゃれで問題が発生したかどうかを尋ねました。これまでのところ、答えは「いいえ」のようです。
この質問はもっと広いです:gccと厳密なエイリアシングについてのホラーストーリーはありますか?
背景:c99-strict-aliasing-rules-in-c-gccでのAndreyTの回答からの引用:
「厳密なエイリアシング規則は、[標準化]時代の初めからCおよびC++に存在していた標準の一部に根ざしています。別の型の左辺値を介して1つの型のオブジェクトにアクセスすることを禁止する条項はC89/ 90(6.3 )およびC ++ 98(3.10 / 15)。...すべてのコンパイラがそれを強制したり依存したりすることを望んでいた(またはあえてした)わけではありません。」
さて、gcc-fstrict-aliasing
は現在、そのスイッチを使って大胆にそうしています。そして、これはいくつかの問題を引き起こしました。たとえば、 Mysqlのバグに関する優れた記事http://davmac.wordpress.com/2009/10/と、http://cellperformance.beyond3d.com/articles/2006/06/understandingの同様に優れたディスカッションを参照してください。 -strict-aliasing.html。
その他の関連性の低いリンク:
- fno-strict-aliasingのパフォーマンスへの影響
- 厳密なエイリアシング
- when-is-char-safe-for-strict-pointer-aliasing
- コンパイル時の検出方法-厳密なエイリアシング
繰り返しになりますが、あなた自身のホラーストーリーはありますか?もちろん、によって示されていない問題が優先されます。-Wstrict-aliasing
また、他のCコンパイラも歓迎します。
6月2日追加: Michael Burrの回答の最初のリンクは、確かにホラーストーリーと見なされますが、おそらく少し古いものです(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;
}
具体的な苦情は次のとおりです。
一部のユーザーは、[上記の]コードが-fno-strict-aliasingなしでコンパイルされると、書き込みとmemcpyの順序が逆になる(つまり、偽のlenがストリームにmemコピーされる)と不満を漏らしています。
CYGWIN wih-O3でgcc4.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
そして、マイケルの答えの2番目のリンクについては、
*(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で問題ないかどうかをSOに尋ねましたが、これまでのところ誰も同意していません。