nDiki : Perl 5.6.0

Perl 5.6.0

2000年3月22日リリース。

warnings プラグマや our などが追加された。

また v1.2.3.4 形式のリテラルが使えるようになった。

約1年後の、2001年4月8日に Perl 5.6.1 がリリースされた。

関連情報

スポンサード リンク

2003年12月23日 (火)

Time::Local::gmtime の範囲チェック

Perl 5.8.x だと、Time::Local::gmtime できちんと範囲チェックが動作している(範囲外だと croak される)のだが、Perl 5.005_03 では必ずしもそうではないようだ。 WiKickerデバッグ中に発見。

でソースを読んでみると、古い Time::Local では cheat サブルーチンで

  • 範囲チェック
  • 指定した年月の開始 gmtime を計算し、%cheat にキャッシュ

している。同一年月での2度目以降 timegm 呼び出しでは %cheat キャッシュを使用して cheat サブルーチンを呼びにいかないので、範囲チェックが実行されないという塩梅。 つまり 2003年1月1日… で一度 timegm を呼び出すと2003年1月に関しては以降 cheat サブルーチンは呼ばれないため、次に 2003年1月33日…で読んでもエラーにしてくれないというわけ(最初に2003年1月33日…で呼んだ場合はちゃんとエラーになるので逆に厄介)。

Perl 5.8.0 以降に標準ではいっている Time::Local ではきちんと毎回チェックする。 うるう年・大の月/小の月も考慮してチェックされる(v5.8.0 より前のでは 31 より大きいかのチェックのみ)。

であり、CPAN では 5.005_03 でも動作する Time::Local パッケージ (1.05~)が公開されている。

Time::Local 1.04 以降を PREREQ_PM にしてもいいのだが、5.005_03 な利用者にとってはインストールするのも面倒か。 最低限のエラーチェックを自前で用意して、互換になるようにした方がいいかな。

スポンサード リンク
[ 12月23日全て ]

2004年7月31日 (土)

Cache::Memcached 1.14 の Perl 5.005_03 対応

1.14 が 7月27日にリリースされていたのでパッチ作成。 1.13 用のパッチがあたったのでそのままいけるかなと思ったが、テストしたところまたいくつかの非互換コードが増えていたのでそれらの修正を行う。

 tar zxvf Cache-Memcached-1.14.tar.gz
 cp -a Cache-Memcached-1.14 Cache-Memcached-1.14.orig
 patch -d Cache-Memcached-1.14 -p1 \
   < Cache-Memcached-1.13-5.005_03-20040605.diff
 find Cache-Memcached-1.14 -name '*.orig' -exec rm {} ';'
 emacs Cache-Memcached-1.14/Memcached.pm
 LC_ALL=C TZ=UTC0 diff -Naur \
   Cache-Memcached-1.14.orig Cache-Memcached-1.14 \
   > Cache-Memcached-1.14-5.005_03-20040731.diff

新規修正点は

  • Socket モジュールでのインポートで IPPROTO_TCP が追加になったところが実験環境でエラー。コードの中では利用していないので削除。
  • ChangeLog 中の下記のため @+ を使うようになったようだが、5.005_03 では定義されていないのでエラー(perl.*delta のどこにものっていないのでチェックに苦労。perlretut に言及があって Perl 5.6.0 から提供されるようになった事を確認)。Cache::Memcached 1.13 で行っている pos を使った処理に戻す。
 2004-07-19
         * don't use pos() because it doesn't seem to work in
           taint mode.  use $+[0] instead.  (Dave Evans <..@djce.org.uk>)

それからパッチの作り方を変更。patch の man の通り LC_ALL=C TZ=UTC0 にするのとオプションを -Naur を使うように。

また 1.14 から String::CRC32 が必要になった。

[ 7月31日全て ]

2005年6月6日 (月)

[ WiKicker ] Storable 永続化データの互換性

fkimura 氏から WiKicker の障害レポートをいただいた。 Perl 5.8.6 へ移行した環境で WiKicker 0.26 を試してみたところエラーになってしまうとのこと。

 "Error
 action: do_read: Byte order is not compatible at blib/lib/Storable.pm
 (autosplit into blib/lib/auto/Storable/thaw.al) line 366,
 at /usr/local/lib/perl5/site_perl/5.8.6/WiKicker/DB/File.pm line 161
 at /usr/local/lib/perl5/site_perl/5.8.6/WiKicker/CGI/AbstractController.pm line 93"

(FreeBSD 4.11-RELEASE-p9)

Storableエラーを吐いている。 Storable データ形式に互換性のない環境 (Perl and/or Storable) 変化があったようだ。

例えば Storableマニュアルによれば 64bit integer をサポートするように構築された Perl 5.6.0 や 5.6.1 で Storable 2.02 以前を使って書き出したデータを他の環境で読み出すと 'Byte order is not compatible' エラーが出るとある。

確認したところ前のバージョンは Perl 5.6.2 だそうなので、もしかしたら上記の非互換性にあたってしまったのかもしれない (FreeBSDPerl って 64bit integer サポートでビルドされるようになっている?)。

WiKicker での対応方法

WiKicker で使用している Perlアップグレードで上記問題にあたった場合、一番簡単な方法は Storable で書き出しているページ情報ファイルを一旦全部消してしまうという方法。

WiKickerデータベースディレクトリ (wikicker.database.directory プロパティで指定しているディレクトリ)の下の、info/basic/* を全て消してしまう(一応バックアップとしてコピーした方が良い)。

この場合、各ページの「最終更新時刻、最終更新者名、要約文」が消えてしまうが、これらの消えてしまった情報は次にページを更新した時に最新の情報で上書きされる。

WikiPage そのものおよび古いリビジョンは影響がなく全て残っているので、通常の運用ではまあ許容できる範囲の対処方法か。

情報ファイルを消したくない場合は、コンバートする必要があるけれど古い Storable データを読み出せる環境で export して、新しい形式で書き直す必要があるので作業する人にとってもちょっと面倒かもしれない。いや、新しい Storable ならば $Storable::interwork_56_64bit あたりを使えば両方をきりかえて読めそうであるので、新しい環境だけあればいいのかな。

[ 6月6日全て ]

2011年5月25日 (水)

なぜ Perl で配列に対して defined を使ってはいけないのか?

defined の挙動で相談されたのでソースコードを見てみたら、配列に対して defined を呼んでいた。 最近の Perl では配列に対して defined を使うのは非推奨である(perldata や perlfunc 参照)。 ほとんどの人が望むような判定結果は返ってこない*1

perl -e '@a = (); print defined @a ? 1 : 0; push @a, 1; print defined @a ? 1 : 0; shift @a; print defined @a ? 1 : 0'

配列が空かどうかならスカラーコンテキストで評価するだけで OK なのだが、Perl プログラミング経験上、1度は defined を使用してしまうだろう。 ただ通常は警告が出るのですぐ気がつく。 この警告は Perl 5.6.0 以降で出る。

 #!/usr/bin/perl

 use warnings;
 use strict;

 my @a = ();
 print defined @a ? "defined\n" : "undefined\n";
 push @a, 1;
 print defined @a ? "defined\n" : "undefined\n";
 shift @a;
 print defined @a ? "defined\n" : "undefined\n";

 # defined(@array) is deprecated at test.pl line 7.
 #         (Maybe you should just omit the defined()?)
 # defined(@array) is deprecated at test.pl line 9.
 #         (Maybe you should just omit the defined()?)
 # defined(@array) is deprecated at test.pl line 11.
 #          (Maybe you should just omit the defined()?)
 # undefined
 # defined
 # defined

しかしながら、配列への参照をデリファレンスしたものに defined を呼んでも警告を出してくれない。 相談ではまっていたのはこのケースだった。

 #!/usr/bin/perl

 use warnings;
 use strict;

 my $a = [];
 print defined @$a ? "defined\n" : "undefined\n";
 push @$a, 1;
 print defined @$a ? "defined\n" : "undefined\n";
 shift @$a;
 print defined @$a ? "defined\n" : "undefined\n";

 # undefined
 # defined
 # defined

なお配列(とハッシュ)に対する defined はメモリが割り当てられたかどうかを得るために使われていた。 Devel::Peek::Dump の結果を見てみると次のような感じ。 配列に要素を push した後に pop して空にしても、メモリは割り当てられた状態になるので defined が真を返すようになるのである。

 #!/usr/bin/perl

 use warnings;
 use strict;
 use Devel::Peek 'Dump';

 my @a = ();
 Dump(\@a);
 push @a, 1;
 Dump(\@a);
 shift @a;
 Dump(\@a);

 # SV = IV(0x9a6d064) at 0x9a6d068
 #   REFCNT = 1
 #   FLAGS = (TEMP,ROK)
 #   RV = 0x9a7dcd8
 #   SV = PVAV(0x9a6e0a8) at 0x9a7dcd8
 #     REFCNT = 2
 #     FLAGS = (PADMY)
 #     ARRAY = 0x0
 #     FILL = -1
 #     MAX = -1
 #     ARYLEN = 0x0
 #     FLAGS = (REAL)
 # SV = IV(0x9a6d184) at 0x9a6d188
 #   REFCNT = 1
 #   FLAGS = (TEMP,ROK)
 #   RV = 0x9a7dcd8
 #   SV = PVAV(0x9a6e0a8) at 0x9a7dcd8
 #     REFCNT = 2
 #     FLAGS = (PADMY)
 #     ARRAY = 0x9a78a20
 #     FILL = 0
 #     MAX = 3
 #     ARYLEN = 0x0
 #     FLAGS = (REAL)
 #     Elt No. 0
 #     SV = IV(0x9a6d064) at 0x9a6d068
 #       REFCNT = 1
 #       FLAGS = (IOK,pIOK)
 #       IV = 1
 # SV = IV(0x9a6d064) at 0x9a6d068
 #   REFCNT = 1
 #   FLAGS = (TEMP,ROK)
 #   RV = 0x9a7dcd8
 #   SV = PVAV(0x9a6e0a8) at 0x9a7dcd8
 #     REFCNT = 2
 #     FLAGS = (PADMY)
 #     ARRAY = 0x9a78a24 (offset=1)
 #     ALLOC = 0x9a78a20
 #     FILL = -1
 #     MAX = 2
 #     ARYLEN = 0x0
 #     FLAGS = (REAL)

ちなみに Perl 5.14.0 の pp_hot.c を見ると以下のようになっている。 配列だと AvMAX が 0 以上になっていれば真になる(十分条件)。 上の例でも pop した後も MAX = 2 となっていることから、defined が真を返しているわけだ。

 PP(pp_defined)
 {
     dVAR; dSP;
     register SV* sv;
     bool defined;
     const int op_type = PL_op->op_type;
     const bool is_dor = (op_type == OP_DOR || op_type == OP_DORASSIGN);

     if (is_dor) {
         PERL_ASYNC_CHECK();
         sv = TOPs;
         if (!sv || !SvANY(sv)) {
             if (op_type == OP_DOR)
                 --SP;
             RETURNOP(cLOGOP->op_other);
         }
     }
     else {
         /* OP_DEFINED */
         sv = POPs;
         if (!sv || !SvANY(sv))
             RETPUSHNO;
     }

     defined = FALSE;
     switch (SvTYPE(sv)) {
     case SVt_PVAV:
         if (AvMAX(sv) >= 0 || SvGMAGICAL(sv) || (SvRMAGICAL(sv) && mg_find(sv, PERL_MAGIC_tied)))
             defined = TRUE;
         break;
     case SVt_PVHV:
         if (HvARRAY(sv) || SvGMAGICAL(sv) || (SvRMAGICAL(sv) && mg_find(sv, PERL_MAGIC_tied)))
             defined = TRUE;
         break;
     case SVt_PVCV:
         if (CvROOT(sv) || CvXSUB(sv))
             defined = TRUE;
         break;
     default:
         SvGETMAGIC(sv);
         if (SvOK(sv))
             defined = TRUE;
         break;
     }

     if (is_dor) {
         if(defined)
             RETURN;
         if(op_type == OP_DOR)
             --SP;
         RETURNOP(cLOGOP->op_other);
     }
     /* assuming OP_DEFINED */
     if(defined)
         RETPUSHYES;
     RETPUSHNO;
 }

結論としては、良い子のみなさんは配列やハッシュに defined を使わないでねということで。

*1以下 Perl 5.14.0 で確認。

今日のさえずり: 気がついたら後頭部ががっつり禿げて、剃るかバーコードかって選択肢

2011年05月25日

  • 08:57 さて、運転再開してるかな?
  • 09:06 京浜東北線走ってた。混雑度は並より少なめなぐらい。
  • 09:13 気がついたら後頭部ががっつり禿げて、剃るかバーコードかって選択肢。
  • 09:16 という夢を今朝みた。禿げの恐怖ってすごい。
  • 09:45 RT @boku: 数ヶ月前から予告していました新会社、株式会社バスキュール号が本日スタートしました。ニュースでもとりあげていただいているようにmixiさんとの共同設立です。http://s.nikkei.com/lVn1Bk 詳細はまたのちほど。
  • 13:00 RT @mixi_PR: ソーシャルグラフを活用した新的なマーケティングを展開してまいります! |バスキュールとミクシィの合弁会社 「株式会社バスキュール号」設立  http://mixi.co.jp/press/2011/0525/8348/
  • 13:48 defined @a は 'defined(@array) is deprecated' って出るけど、defined @$a は出ない。 #Perl
  • 14:04 塩牛丼セット 520円。 (@ 神戸 らんぷ亭 渋谷並木橋店) http://4sq.com/ioBjBa
  • 14:33 托鉢にひさびさ遭遇。
  • 14:44 インクタンク購入。PGBK がたまってるので今日はバラで。 (@ ビックカメラ 渋谷東口店) http://4sq.com/kR74Yq
  • 15:11 'defined(@array) is deprecated' が入ったのは Perl 5.6.0。 #Perl
  • 15:30 perl -e '@a = (); print defined @a ? 1 : 0; push @a, 1; print defined @a ? 1 : 0; shift @a; print defined @a ? 1 : 0'
  • 15:31 たしかにこれは直感的じゃないね。 #Perl
  • 19:40 退勤。
  • 19:50 Twitter、reply 通知メール送られるようになったんだ。
  • 20:06 無くなってる。 (@ 丸善 エキュート品川店) http://4sq.com/kZ0b6W
  • 20:09 これになってた。 (@ Smith エキュート品川) http://4sq.com/mHMgxb
  • 23:39 あ、そんなオプションがあるんですね。 RT @__gfx__: use warnings FATAL =&gt; 'all'; してるとFATALになるので問題はないんだけども。
  • 23:58 イベント用に ID ケース買ったよ。 http://flic.kr/p/9LQm8K
  • 24:09 名札をぶらさげようっていう @smokemonkey のアイデア http://bit.ly/jZ5mrR がいいなと思って。結局同じものになっちゃったけど(スリップオン好き・オレンジ好き・お店にあったなかでこれが一番手頃で好みだったで)。
[ 5月25日全て ]

2017年9月15日 (金)

Perl バージョンと perl バージョンの表記

Perlプログラミング言語を指し、 perl は Perl で書かれたプログラムを実行するプログラムというには良く知られています。

Perl 5.6.0 から v1.2.3.4 というリテラル形式が v-strings が出てきたので Perl v5.6.0 のように表記したりしていたのですが、調べてみると v-strings でバージョン番号を示しているのは perl に対しての場合が多く (perl -v でも v-strings で出力される)、Perl については v はつけない方がほとんどでした。

なので nDiki での Perl バージョン表記する際は v をつけないように修正・統一してみました。

[ 9月15日全て ]

About Me

Naney Naney (なにい)です。株式会社ミクシィでマネージャー・プロダクトオーナーをしています。

nDiki1999年1月に始めたコンピュータ日誌を前身とする NaneyWeb 日記(兼パーソナルナレッジベース)です。ちょっとしたノートは nNote にあります。

follow us in feedly

※内容は個人的見解であり所属組織とは関係ありません。

月別インデックス
Process Time: 0.065689s / load averages: 0.58, 0.51, 0.42
nDiki by WATANABE Yoshimasa (Naney, Google profile)
Powered by DiKicker