アプリ版:「スタンプのみでお礼する」機能のリリースについて

あるCGIを開発しているのですが動作確認してみたところ


Attempt to free unreferenced scalar: SV 0xXXXXXXX, Perl interpreter: 0xXXXXXX at XXX.cgi line XX.

のようなエラーがでるようになりました。
調べてみると

http://perldoc.jp/docs/perl/5.6.1/perldiag.pod

> (W) Perl がスカラの参照カウントをデクリメントしようとして、0 になるかを見たところ、既に 0 になっていることがわかりました。これは、既に解放されているべきものであり、実際は、おそらく、解放されたものでしょう。これは、SvREFCNT_dec() が必要以上に呼ばれたか、SvREFCNT_inc() が必要なときに呼ばれなかったか、SV が消滅すべきで無いときに消滅してしまったか、メモリ異常になったことが考えられます。

と書いてあるのですが意味が分かりません。
どなたか主にこのエラーが発生する具体的な要因や解決方法などを
教えていただけないでしょうか。
なお、ローカルの環境(04WebServer+Active Perl v5.10.0 build 1002)
では正常に動作するのに本番機(IIS+Active Perl v5.8.8 build 817)で
このような現象がでています。

エラーのでている部分のスクリプトは申し訳ありませんが事情で
提示できないのであくまでこういう時に発生するというような情報と
解決策があるだけでよろしいです。

他に必要な情報があれば書いていただいたことはなるべく調べて回答
するようにします(ただし調べきれない場合もあると思います)。
ただ、返事の方が動作確認できない状態になるため1週間後辺りに
なります。

よろしくお願いします。

A 回答 (3件)

これはまたえらく複雑なことをしていますね。



5.10で確認して起きないということであれば、Perlのバグとみてよいかと思います。
5.8→5.10で内部構造的に結構変わっているので、該当するバグのフィックスがあったかどうか
というのはわかりません。

sub regex とその中で作っている無名サブルーチンで、同じような
my $foobra = shift というパターンをしているのがちょっと気になるといえば気になります。
サブルーチンが増えるというのが気にならないのであれば、
現在無名サブルーチンになっているのを名前をつけて独立したサブルーチンにした上で
置換部で呼び出してみたらどうでしょうか?

この回答への補足

どうも、返事が遅くなりました。

> これはまたえらく複雑なことをしていますね。

そうなんですよね。
正規表現はPerlの要の一つなんですけどどうも苦手で...。
(苦手意識があるから余計に難しく感じているのかも)

> 5.10で確認して起きないということであれば、Perlのバグとみて
> よいかと思います。
> 5.8→5.10で内部構造的に結構変わっているので、該当するバグの
> フィックスがあったかどうか
> というのはわかりません。

他のPerl 5.10.0で確認はしていないので明確なところは分かりませんが
可能性は高そうです。
すべて確認したのはOSがWinでPerlもActive Perlなので他のPerlでは
どうなのかも分かりませんが本番機もWin+Active Perl 5.8.8でしかも
勝手にバージョンアップとかするわけに行かないということもあり、
スクリプトの方を修正せざるを得ない状況です。
最初、本番機でテストしてみようとしたらヘッダを出力しているにも
関わらず何故かヘッダがないと怒られまして何故だろうといろいろ
調べてみるとどうやらPerlが強制終了してそれまでSTDOUTに出力した
内容が消失していたみたいです。

> sub regex とその中で作っている無名サブルーチンで、同じような
> my $foobra = shift というパターンをしているのがちょっと気に
> なるといえば気になります。
> サブルーチンが増えるというのが気にならないのであれば、
> 現在無名サブルーチンになっているのを名前をつけて独立した
> サブルーチンにした上で
> 置換部で呼び出してみたらどうでしょうか?

my宣言しているので大丈夫なはず...とは思いましたが一応、
やってみました。
しかし、やはり同様のようです。

不思議なのが前回書いたように何かの処理を行ったりprintで不要な
文字列を出力させたりすると発生しなくなったりすることがあると
いう点です。
上記にも書いたようにPerlが強制終了しているようなのでやはり
Perlのバグの可能性は濃厚です。
と同時に問題の起こっている正規表現部分も実際には意図したとおりに
動いているようなのですが、間違っている可能性が高く自信がないので
同様の動作をしながらもっと適切な書き方があったらよろしくお願い
します。

$$str には複数行の文字列が入っていてその中から$patternにマッチ
する特定のパターンを抽出し(このパターンは複数行&同一行で複数回
パターンにマッチする可能性あり)それを特定の変数などに置換、
それで変換した結果、そのパターンがあった行がスペースのみになった
時はすべて除去、みたいな感じです。
(一部説明が間違っているかも)

具体的には http://oshiete1.goo.ne.jp/qa4213045.html の質問の
回答から試行錯誤した上で自分で考え出した正規表現なのですが非常に
ややこしくなっています。
まだ、上記の質問も締め切っていませんので宜しければそちらも
お願いします。

補足日時:2008/08/09 22:32
    • good
    • 0
この回答へのお礼

あれから調べてみた限りでは

http://d.hatena.ne.jp/usuihiro1978/20080107

に関する不具合なのかなと思います。
まだ、根本的に解決できていませんが質問してからずいぶん経って
しまったのでいったん締め切って後ほど新たに質問し直そうと思います。
ありがとうございました。

お礼日時:2008/08/19 16:19

特にこれが怪しいというモジュールはないですね。



> 前後で終了させたりして調べてみるとどうやら正規表現でsによって
> 文字列を置換した後に問題が起こっているようなのですが見てみても
> 問題はなさそうなんです。

どんな感じの置換を行っているんでしょうか? e 修飾子を複数個つけてたりはしていませんか?

Perl Internalsについて - Unknown::Programming
http://d.hatena.ne.jp/fbis/20080627/1214537750

で紹介されている
Internals::SvREFCNT($foo);
を使って、問題の正規表現に関連している変数を調べてみてはどうでしょうか?

この回答への補足

この正規表現が非常にややこしい状態で正規表現での置換は全部
成功しているようなのですが最後に通ったときに何かおかしくなって
いるのでメモリ上のデータに何か問題があるのかも知れません。
(サブルーチンにリファレンスでデータを渡してそのサブルーチンの
中でデリファレンスしeで無名サブルーチンを実行しています)

なお、以下で回答してからまたあれこれ調べてみてひとつ分かったことが
あります。
それはどうやら Perl 5.8.8 でエラーがでているようです。
別の5.8.8がインストールされている環境でも同様のエラーがでました。
この環境のPerlのバージョンを5.10.0にして試したわけではないのですが
もしそうならPerl側に問題がある可能性が非常に高く、5.10.0までに
修正されたと見た方がいいのでしょうか。
(本番機は自分のものではなく自由にいじれるわけではないのでPerlの
バージョンアップは多分できません)

更に不思議なのが同様の正規表現をパターンマッチでif内で一度判定
させて、その中で置換してやると正常に通るようです。

sub regex {
my $str = shift;
my $VAR = shift;
my $pattern = shift;
my $replace = shift;
my $func = sub {
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;
};

if($$str =~ /((([^\n]*?)$pattern(?=.*))+(\n?))/gs) { # この if を追加
$$str =~ s/((([^\n]*?)$pattern(?=.*))+(\n?))/&$func($1, $VAR, $pattern, @$replace)/egs;
}
return;
}

結果的にこのような感じにしたら取り敢えず今回は正常に動作している
ようなのですがなんか面倒だし原因もよく分からず納得いかない状態
で...。
(根本的な原因を理解して取り除かないとまた同様の問題が発生する
可能性が高いというのもありますし)

正規表現部分は結構試行錯誤して自力でやったものなので間違っている
可能性があります(これが原因だったりして...)
正規表現は難しすぎてよく分かりません。

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

いくらなんでもこれだけの情報でどうにかしろと言うのは無理と言うものでしょう。



>どなたか主にこのエラーが発生する具体的な要因や解決方法などを
>教えていただけないでしょうか。

要はPerlの変数管理がおかしくなってしまったということです。
・Windows以外のたとえばLinuxをつかったどれかのディストロでも起きるか?
・使っているモジュールには何があるか。特に自作のXS使用のものはあるか
・スレッドを使っているか

あたりはどうでしょうか?
純粋に自分がPerlのコードしか書いていない(Cによる拡張を使っていない)
のであれば、Perl本体のバグの可能性もあります。

この回答への補足

えっと、すみません。

現状で使用しているモジュールで分かるのは

CGI::Carp
File::Spec
File::Basename
Cwd
Tie::IxHash
Encode
File::Path
CGI::Session
Data::Dumper

のようです。
自作モジュールは使用していません。
一部を除き、ほとんどは標準モジュールであとはスクリプトの下に
置いて use lib でインクルード場所を指定し読み込んでいます。
スレッドは多分使っていないと思います。
(使用しているモジュール内で使用していない限り)

前後で終了させたりして調べてみるとどうやら正規表現でsによって
文字列を置換した後に問題が起こっているようなのですが見てみても
問題はなさそうなんです。
(しかも、何回かその部分を使用しているのですがある一定の
タイミングのみ?で起こっているようです)

Linuxでの動作確認はできればしたいと思いますが現在、環境を
用意できないのですぐには確認できないと思います。

あとはよく分かりません。

補足日時:2008/08/08 22:14
    • good
    • 0

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