jcode.pl でエラー「defined(%hash) is deprecated」の対応方法


[初回公開] 2020年05月27日

CGI の Perl は最近ではあまり利用されなくなったプログラム言語だが、今でもウェブサイトやシステムでは稼働中のところがあるものの新しいサーバで動作させるとブラウザに「500 Internal Server Error」が表示され「defined(%hash) is deprecated」のエラーで正常動作しない場合の対応方法について紹介する。

jcode.pl でエラー「defined(%hash) is deprecated」の対応方法

1.Perl で「500 Internal Server Error」が表示されたときの原因調査方法

Perl で「500 Internal Server Error」が表示されたときの原因調査方法としては、ウェブサーバのログを確認する。
同じ CGI の PHP は設定によりブラウザにエラー内容を表示することができるが、Perl はブラウザにエラーが表示されないため調査にはログを参照するか手段がない。



また、ブラウザによっては HTTP のステータスコードが 500 の場合は真っ白になり何も表示されないことがある。
そのため、HTTP ステータスコードが 500 以外のエラーも考えられるため、利用しているブラウザの開発者モードで HTTP ステータスコードを確認することも必要になる。

2.Perl のエラーログの確認方法

Perl のエラーログの確認方法としては、ウェブサーバのログファイルを参照する。
ログファイルは利用しているサーバ環境によって違うが、多くはディレクトリ「httpd」内にアクセスログとエラーログで分かれていることが多い。

ウェブサーバが Apache の場合はディレクトリ「/var/log/httpd/」内にあるエラーログファイル(error_log)を参照する。
エラーログのファイルは FTP でダウンロードしたり、SSH によるコマンド操作で閲覧が可能で、一例として下記のように記述されることがある。

defined(%hash) is deprecated at ./jcode.pl line ***)

エラーログにはエラーになった原因の他、エラーとなったプログラムファイル名とプログラムの箇所(行数)を把握することができる。

3.エラー「defined(%hash) is deprecated」の原因

前述の例に挙げたエラー「defined(%hash) is deprecated」の原因は、プログラムとして記述している関数 defined(%hash) が非推奨になっていることを示している。

これは Perl のバージョンが上がったことにより発生するもので、レンタルサーバなどホスティングではサーバ運営者が Perl をアップデートしたり、新しいサーバ OS に移設する場合は常に最新版の Perl がインストールされるため、これまで動作していたプログラムファイルが対応できずにエラーになる。

4.エラー「defined(%hash) is deprecated」の対応方法

エラー「defined(%hash) is deprecated」の対応方法としては、define を利用しないようにして連想配列の使い方を変更する。



Perl の「連想配列」は hash(ハッシュ)と呼ばれ、変数名の前に % を付与して表す。
Perl に用意されている関数 defined は引数の値が定義されているかを True か False で返すものだが、Perl のバージョンが上がったことで非推奨となった

そのため、文字コードを取り扱うライブラリ jcode.pl のプログラムでは下記の 2 箇所から下記のように削除する。

sub z2h_euc {
local(*s, $n) = @_;
&init_z2h_euc unless defined %z2h_euc;
$s =~ s/($re_euc_c|$re_euc_kana)/$z2h_euc{$1} ? ($n++, $z2h_euc{$1}) : $1/geo;
$n;
}

sub z2h_euc {
local(*s, $n) = @_;
&init_z2h_euc if !%z2h_euc;
$s =~ s/($re_euc_c|$re_euc_kana)/$z2h_euc{$1} ? ($n++, $z2h_euc{$1}) : $1/geo;
$n;
}

sub z2h_sjis {
local(*s, $n) = @_;
&init_z2h_sjis unless defined %z2h_sjis;
$s =~ s/($re_sjis_c)/$z2h_sjis{$1} ? ($n++, $z2h_sjis{$1}) : $1/geo;
$n;
}

sub z2h_sjis {
local(*s, $n) = @_;
&init_z2h_sjis if !%z2h_sjis;
$s =~ s/($re_sjis_c)/$z2h_sjis{$1} ? ($n++, $z2h_sjis{$1}) : $1/geo;
$n;
}

また、jcode.pl の define の前に「unless」があり、これは条件式が偽の場合に処理させたいときに記述する。
unless も Perl の最新バージョンでは利用できなくなる恐れがあるため、if 文で否定条件を示す ! を連想配列の前に付けている。

もし「defined」を消すだけであれば連想配列の前の ! は不要となる。

関連記事

コメントを残す