[Armadillo:08318] Perl-5.8.8 をArmadillo-4x0で動かすと実数がおかしくなる
Yasuhisa Nakamura
email@hidden
2012年 9月 12日 (水) 18:30:25 JST
中村です。
ちょっと長いです。
ずいぶん前の記事になりますが、[Armadillo:06167]
http://lists.atmark-techno.com/pipermail/armadillo/2010-November/006167.html
で、Perl-5.8.8をatmark-distでビルドできるようにするパッチが
竹之下さんにより投稿されていました。
これを使えばPerlでCGIや単独スクリプトなど簡単に書けるようになり、
便利に使わせていたいだています。
竹之下さん、ありがごうございます。
5.8.8と、かなり古いバージョンですから、今でもこのバージョンを
使われている方が現在どのくらいいるのかわかりませんが、
Armadillo-4x0で使っていて、実数で次のような不具合がありましので、
その現象と対処方法をお知らせします。
次のものは正常です。
perl -e 'print 1327402000+0,"\n"'
1327402000
perl -e 'print 1327402000+10,"\n"'
1327402010
perl -e 'print 1327402000+100,"\n"'
1327402100
perl -e 'print 1327402000+1000,"\n"'
1327403000
実数にすると、次のようにおかしくなります。
perl -e 'print 1327402000+0.0,"\n"'
1327401984.24578
perl -e 'print 1327402000+10.0,"\n"'
1327401984.24578
perl -e 'print 1327402000+100.0,"\n"'
1327401984.24578
perl -e 'print 1327402000+1000.0,"\n"'
1327401984.24578
perl -e 'print 1327402000.0,"\n"'
1327401984.24577
perl -e 'print 1327402010.0,"\n"'
1327401984.24577
perl -e 'print 1327402100.0,"\n"'
1327401984.24577
perl -e 'print 1327403000.0,"\n"'
1327401984.24577
これら結果の"1327401984.24578"や"1327401984.24577"の
小数点以下の部分".24578"や".24577"は、ビルドしなおすと
これとは異なる表示になりますので、ゴミを拾っている感じです。
// 1327402000という数値は、この問題に遭遇したときに
// 使っていた値で、特別な意味はありません。
この現象は、Perl-5.8.8のオリジナルソースをデフォルトのまま
(Perl-5.8.8のソースを展開しただけの状態で)
次のようにクロスコンパイルしたmicroperlでは発生ません。
make -f Makefile.micro CC=/usr/bin/arm-linux-gnueabi-gcc
しかし、最適化の"-O2"をつけて、
make -f Makefile.micro CC=/usr/bin/arm-linux-gnueabi-gcc OPTIMIZE=-O2
としてビルドしたmicroperlでは、同じ症状が発生します。
Armadillo-220(ATDE2環境)では"-O2"をつけてもこの問題は発生しません。
また、ATDE3環境でx86用として
make -f Makefile.micro OPTIMIZE=-O2
としたmicroperlを使った場合も問題は出ません。
gccのバージョンは、
Armadillo-220の開発環境ATDE2
gcc version 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
Armadillo-400の開発環境ATDE3(x86用のgccもarm-linux-gnueabi-gccも)
gcc version 4.3.2 (Debian 4.3.2-1.1)
でした。
Armadillo-4x0の開発環境であるATDE3に入っているarm用gccの
最適化のバグか、あるいは、最適化の影響を受けて誤動作する
コードがperlのソースにあるものと思われます。
たくさんあるperlのソースコードの中で問題となっているものを
探してたところ、sv.cにだけ"-O2"を付かなければ、この問題を
回避できることがわかりました。
竹之下さんさんのパッチを使ってatmark-distに組み込んだperl-5.8.8を
ビルドする場合には、cflags.SHに次のパッチをあてれば、
sv.cだけ最適化をナシ("-O0")にすることができます。
--- src/atmark-dist/trunk/user/perl/cflags.SH-orig
+++ src/atmark-dist/trunk/user/perl/cflags.SH
@@ -113,11 +113,11 @@
pp_sys) ;;
regcomp) ;;
regexec) ;;
run) ;;
scope) ;;
- sv) ;;
+ sv) optimize=-O0;;
taint) ;;
toke) ;;
usersub) ;;
util) ;;
*) ;;
なお、perl-5.8.9ではこの問題は発生しませんでした。
perl-5.8.8とperl-5.8.9のsv.cを見比べてみましたが、
5.8.8から5.8.9でかなりの修正がなされており、sv.cの中の
どこが問題になっていたのか?までは特定できていません。
(この特定ができれば、今後自分でArmadillo-4x0用のCの
プログラムを書くときに、こういう書き方をしたら環境や
最適化依存のバグになる、というのがわかるのですが・・・)
perl-5.10.1でmicroperlをクロスコンパイルしたものでも
"-O2"のこの問題は発生しませんでした。
それ以降のperl(5.12.x以降)は、上に書いた方法での
microperlのクロスコンパイルができなくなってしまっているので、
試していません。
Armadillo-4x0でperl-5.8.8をお使いの方のお役にたてれば、
幸いです。
--
なかむら
armadillo メーリングリストの案内