- ベストアンサー
Attempt to free unreferenced scalarとは?! エラーの原因と解決方法を教えてください
- CGI開発中に”Attempt to free unreferenced scalar”エラーが発生しました。具体的な要因や解決策を教えてください。
- エラーメッセージ「Attempt to free unreferenced scalar: SV 0xXXXXXXX, Perl interpreter: 0xXXXXXX at XXX.cgi line XX.」について、意味が分かりません。解釈や解決策を教えてください。
- ローカル環境では正常に動作しているCGIが、本番機で”Attempt to free unreferenced scalar”エラーが発生します。具体的な原因と解決方法を教えてください。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
これはまたえらく複雑なことをしていますね。 5.10で確認して起きないということであれば、Perlのバグとみてよいかと思います。 5.8→5.10で内部構造的に結構変わっているので、該当するバグのフィックスがあったかどうか というのはわかりません。 sub regex とその中で作っている無名サブルーチンで、同じような my $foobra = shift というパターンをしているのがちょっと気になるといえば気になります。 サブルーチンが増えるというのが気にならないのであれば、 現在無名サブルーチンになっているのを名前をつけて独立したサブルーチンにした上で 置換部で呼び出してみたらどうでしょうか?
その他の回答 (2)
- sakusaker7
- ベストアンサー率62% (800/1280)
特にこれが怪しいというモジュールはないですね。 > 前後で終了させたりして調べてみるとどうやら正規表現で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; } 結果的にこのような感じにしたら取り敢えず今回は正常に動作している ようなのですがなんか面倒だし原因もよく分からず納得いかない状態 で...。 (根本的な原因を理解して取り除かないとまた同様の問題が発生する 可能性が高いというのもありますし) 正規表現部分は結構試行錯誤して自力でやったものなので間違っている 可能性があります(これが原因だったりして...) 正規表現は難しすぎてよく分かりません。
- sakusaker7
- ベストアンサー率62% (800/1280)
いくらなんでもこれだけの情報でどうにかしろと言うのは無理と言うものでしょう。 >どなたか主にこのエラーが発生する具体的な要因や解決方法などを >教えていただけないでしょうか。 要は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での動作確認はできればしたいと思いますが現在、環境を 用意できないのですぐには確認できないと思います。 あとはよく分かりません。
お礼
あれから調べてみた限りでは http://d.hatena.ne.jp/usuihiro1978/20080107 に関する不具合なのかなと思います。 まだ、根本的に解決できていませんが質問してからずいぶん経って しまったのでいったん締め切って後ほど新たに質問し直そうと思います。 ありがとうございました。
補足
どうも、返事が遅くなりました。 > これはまたえらく複雑なことをしていますね。 そうなんですよね。 正規表現は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 の質問の 回答から試行錯誤した上で自分で考え出した正規表現なのですが非常に ややこしくなっています。 まだ、上記の質問も締め切っていませんので宜しければそちらも お願いします。