プロが教える店舗&オフィスのセキュリティ対策術

Attempt to free unreferenced scalar とは?
http://oshiete1.goo.ne.jp/qa4237453.html

の続きです。
とりあえず、下に現状で分かる最小限の再現性があるスクリプトを
書いておきます。

print &opentmpl("body");
print &opentmpl('footer'); # これがない場合はエラーにならない

sub opentmpl {
my $fn = shift;
my $VAR = shift || {};
my $file = &{$fn}();
&regex(\$file, $VAR, '__([A-Z_\d]+?(\[\d+?\])?)__', ['$VAR->{"%s"}', '$1']);
&regex(\$file, $VAR, '&{(.+?)}&', ['%s', '$1']);
return $file;
return undef;
}

sub regex {
my $str = shift;
my $VAR = shift;
my $pattern = shift;
my $replace = shift;
$$str =~ s/((([^\n]*?)$pattern(?=.*))+(\n?))/&func($1, $VAR, $pattern, @$replace)/egs;
return;
}

sub func {
my $str = shift;
my $VAR = shift;
my $pattern = shift;
my $buf = shift;
$str =~ s/$pattern/$@ = ''; $_ = eval(sprintf($buf, map { eval($_); } @_)); $@ ? $@ : $_/egs;
if($str =~ /^\s*\n?$/s) {
return;
}
return $str;
}

sub body {
print "Content-type: text/plain; charset=shift_jis\n\n";
return <<'HTML';
&{
return &opentmpl('table', {'TEST' => 'test'});
}&
HTML
}

sub table {
return <<'HTML';
__TEST__
HTML
}

sub footer {
return <<'HTML';
test
HTML
}

調べてみた限りではActivePerl for Win32以外のPerlでも同様のよう
です。
(Linux上でも同様のようです)

5.8.8ではエラーになりますが、5.10.xではエラーにならないようです。
(同じ環境において5.8.8では再現し、5.10.0にバージョンアップすると
再現しなくなり、再度5.8.8にバージョンダウンすると再現します)
本番機の環境が5.8.8で勝手にバージョンアップなどができないため、
5.8.8で正常に動作するようにするにはどうしたらよいでしょうか。

結構、無駄も多いと思いますので全く同じ動作をしながらより効率の
いい書き方ができたらいいなと思います。
(なお、実際には使用しているけど上記では使用していない部分が
含まれていてその部分がない場合もエラーにならないようです)

A 回答 (3件)

とりあえず,再現しません.



This is perl, v5.8.8 built for MSWin32-x86-multi-thread
(with 18 registered patches, see perl -V for more detail)

Copyright 1987-2007, Larry Wall

Binary build 822 [280952] provided by ActiveState http://www.ActiveState.com
Built Jul 31 2007 19:34:48

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl". If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.

perl test.pl
Content-type: text/plain; charset=shift_jis

test

test
============
use strict;
use warnings;
してないととか,サブルーチンの呼び出しに&をつけてるとか
どういう結果が期待しているものなのか不明だったりしますが,
#5.8.10でうごくんなら,その「期待された結果」を明示すべきだと
#思うけどね

こんな感じでうごく?
そもそももっと「読めるコード」にすべき.
しばらくたって自分でこのコードのやってること読めますか?
私はまったく読めません.

use strict;
use warnings;

my %subs=(
"body" => sub {
print "Content-type: text/plain; charset=shift_jis\n\n";
return <<'HTML';
&{
return opentmpl('table', {'TEST' => 'test'});
}&
HTML
},
"table" => sub {
return <<'HTML';
__TEST-TABLE__
HTML
},
"footer" => sub {
return <<'HTML';
test-footer
HTML
},
);

print opentmpl("body");
print opentmpl('footer'); # これがない場合はエラーにならない

sub opentmpl {
my $fn = shift;
my $VAR = shift || {};
my $file = $subs{$fn}->();
regex(\$file, $VAR, '__([A-Z_\d]+?(\[\d+?\])?)__', ['$VAR->{"%s"}', '$1']);
regex(\$file, $VAR, '&{(.+?)}&', ['%s', '$1']);
return $file;
}

sub regex {
my $str = shift;
my $VAR = shift;
my $pattern = shift;
my $replace = shift;
$$str =~ s/((([^\n]*?)$pattern(?=.*))+(\n?))/func($1, $VAR, $pattern, @$replace)/egs;
return;
}

sub func {
my $str = shift;
my $VAR = shift;
my $pattern = shift;
my $buf = shift;
$str =~ s/$pattern/$@ = ''; $_ = eval(sprintf($buf, map { eval($_); } @_)); $@ ? $@ : $_/egs;
if($str =~ /^\s*\n?$/s) {
return;
}
return $str;
}

この回答への補足

どうも、すみません。

現象が再現しているActivePerlは perl -v してみたところbuild 817の
ようです。
(確認したLinuxの方のPerlはちょっと分かりません)

This is perl, v5.8.8 built for MSWin32-x86-multi-thread
(with 25 registered patches, see perl -V for more detail)

Copyright 1987-2006, Larry Wall

Binary build 817 [257965] provided by ActiveState http://www.ActiveState.com
Built Mar 20 2006 17:54:25

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl". If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.


> use strict;
> use warnings;

これはしていません。
(実際のスクリプトの方では strict だけしています)

> #5.8.10でうごくんなら,その「期待された結果」を明示すべきだと
> #思うけどね

ごめんなさい。

上記のサンプルの方では

Content-type: text/plain; charset=shift_jis

test

test

のような表示が出るはずです。

> こんな感じでうごく?

やはりエラーが出ているようです。

> そもそももっと「読めるコード」にすべき.
> しばらくたって自分でこのコードのやってること読めますか?
> 私はまったく読めません.

本当にすみません。
ぼくもそう思います(いつもこれで苦労していますがこれ以上うまく
組めなくて...)。

補足日時:2008/08/27 12:05
    • good
    • 0
この回答へのお礼

補足の所は既に書いちゃったのでこちらに失礼します。

いろいろ、過去のバージョンなどを順にインストールして調べてみた
ところどうやら、build 822で修正された問題のようです。
(build 821がDLできないので正確に確認できていませんが820では
現象が再現し、822では再現しませんでした)

現象の発生するサンプルは今、もうちょっと簡略化できないか
いろいろやっています。
既にずいぶん経っているため、新しい回答はないと思いますので
いったん質問を閉じてから再質問しようと思います。

お礼日時:2008/08/28 17:57

なるほど・・821からですか.


#そろそろ5.10にうつろうかな・・・Pugsでもいいんだけど(笑)

>現象の発生するサンプルは今、もうちょっと簡略化できないか

一応,シンプルにするためにソフトリファレンスを
ディスパッチテーブル(ハッシュ)にしたりする方法を
書いたのですが。。。

あとはサブルーチン,regex・・・これは本当に必要なのかな
それから,ややこしい正規表現を書くときには
xオプションも考えるべきでしょうね.
参照:Perlベストプラクティス(D.Conway,オライリー)

この回答への補足

> あとはサブルーチン,regex・・・これは本当に必要なのかな
> それから,ややこしい正規表現を書くときには
> xオプションも考えるべきでしょうね.

そうですね。
正規表現って結構難しいので行き当たりばったりでいろいろ試して
結果的に意図したとおりに動作する(していると思われる)ものを
採用しただけですので無駄があったりおかしな事やっている可能性が
高いです。
xオプションの使い方がよく分からないのですけど、余裕があったら
調べてみたいと思います。

具体的には '__([A-Z_\d]+?(\[\d+?\])?)__' か '&{(.+?)}&' に
マッチする行を変換しているのですがその際に、1行内で複数回マッチ
する場合があり、そして変換結果が空白文字列(\s)だけだったら
その行を削除してしまいたいんです。
(ただし、パターンが含まれていない行はそのままにしたいので一度、
パターンが含まれている行を取得してその行を変換した結果から判断
しています)

あと、前回の質問の補足にも書いたのですがどうやら、 regex の
正規表現の部分の直前に

if($$str =~ /$pattern/s)

のような正規表現のマッチを加えるとなぜかエラーにならなくなります。
現状ではこれで何とか回避しているのですけど、かなり不安があり
ます。

補足日時:2008/09/01 14:11
    • good
    • 0

参考情報。



Build 821 Wednesday, Jun 24, 2007

Build 821 is based on Perl 5.8.8, but also includes all changes from the Perl 5.8 maintenance branch up to change 31223 plus additional selected changes from the Perl 5.9 development branch.

Build 821 was only distributed for HP-UX.

これから考えると、Build 820 → Build 821で加えられた修正が効いているのでは?
ただし最後の行にあるように、Build 821としてリリースされたのは
HP-UX向けだけと。
    • good
    • 0
この回答へのお礼

どうもありがとうございます。

821か822のどちらかで修正されていることはまあ、間違いないと思います。
ただ、直接それに関する問題なのか他の問題が影響していてそれを
修正した時に関連して結果的に修正されたのかは分かりません。

お礼日時:2008/09/01 14:11

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!