From: Naohisa Goto Date: 2011-10-21T13:24:50+09:00 Subject: [ruby-dev:44657] [Ruby 1.9 - Bug #5469][Open] Bus Error when accessing NAN and INFINITY Issue #5469 has been reported by Naohisa Goto. ---------------------------------------- Bug #5469: Bus Error when accessing NAN and INFINITY http://redmine.ruby-lang.org/issues/5469 Author: Naohisa Goto Status: Open Priority: Normal Assignee: Category: Target version: ruby -v: - 現在、INFINITYやNANが処理系で定義されていない場合、numeric.c 内の以下の変数を使います。 const unsigned char rb_infinity[] = "\x00\x00\x80\x7f"; const unsigned char rb_nan[] = "\x00\x00\xc0\x7f"; (上記はlittle endianの場合のみピックアップ) しかし、この記述はワード境界のアラインメントを一切考慮していないため、 処理系とCPUアーキテクチャの組み合わせによっては、Bus Error が出ます。 具体的には、Sparc Solaris 10 上の Fujitsu C Compiler 5.6 で作成すると Bus Error が出ました。 以下のパッチのように共用体にすると大丈夫でした。 ただしバイナリ互換性は保たれなくなる気がします。 同じ記述は 1.9.3 にもありますが、メジャーな環境では起きていないようなので、バックポートする必要はないと思います。 =================================================================== --- include/ruby/missing.h (revision 33498) +++ include/ruby/missing.h (working copy) @@ -124,20 +124,27 @@ RUBY_EXTERN double cbrt(double); #endif +#if !defined(INFINITY) || !defined(NAN) +union bytestream4_or_float { + unsigned char stream[4]; + float float_value; +}; +#endif + #ifdef INFINITY # define HAVE_INFINITY #else /** @internal */ -RUBY_EXTERN const unsigned char rb_infinity[]; -# define INFINITY (*(float *)rb_infinity) +RUBY_EXTERN const union bytestream4_or_float rb_infinity; +# define INFINITY (rb_infinity.float_value) #endif #ifdef NAN # define HAVE_NAN #else /** @internal */ -RUBY_EXTERN const unsigned char rb_nan[]; -# define NAN (*(float *)rb_nan) +RUBY_EXTERN const union bytestream4_or_float rb_nan; +# define NAN (rb_nan.float_value) #endif #ifndef isinf Index: numeric.c =================================================================== --- numeric.c (revision 33498) +++ numeric.c (working copy) @@ -66,16 +66,16 @@ #ifdef HAVE_INFINITY #elif !defined(WORDS_BIGENDIAN) /* BYTE_ORDER == LITTLE_ENDIAN */ -const unsigned char rb_infinity[] = "\x00\x00\x80\x7f"; +const union bytestream4_or_float rb_infinity = { 0x00, 0x00, 0x80, 0x7f }; #else -const unsigned char rb_infinity[] = "\x7f\x80\x00\x00"; +const union bytestream4_or_float rb_infinity = { 0x7f, 0x80, 0x00, 0x00 }; #endif #ifdef HAVE_NAN #elif !defined(WORDS_BIGENDIAN) /* BYTE_ORDER == LITTLE_ENDIAN */ -const unsigned char rb_nan[] = "\x00\x00\xc0\x7f"; +const union bytestream4_or_float rb_nan = { 0x00, 0x00, 0xc0, 0x7f }; #else -const unsigned char rb_nan[] = "\x7f\xc0\x00\x00"; +const union bytestream4_or_float rb_nan = { 0x7f, 0xc0, 0x00, 0x00 }; #endif #ifndef HAVE_ROUND -- http://redmine.ruby-lang.org