Perlのエラーメッセージのコーナー。
2週間に一度、水曜日は、Perlのエラーメッセージが表示される最小のプログラムを書いて、どういうときにどう怒られるかを研究する。
(今回もスッキリしません。)
今回は
これは
2週間に一度、水曜日は、Perlのエラーメッセージが表示される最小のプログラムを書いて、どういうときにどう怒られるかを研究する。
(今回もスッキリしません。)
今回は
Repeat count in pack overflowsである。
これは
(S:主語) Repeat count in pack = packの中の繰り返し数がということで、
(V:動詞) overflows = オーバーフローした
「packの中の繰り返し数がオーバーフローした」ということだ。
pack関数「pack TEMPLATE, LIST」において、TEMPLATEは数字を含むことがある。
たとえば以下のプログラムを見てみる。
'U4'というのはUnicode文字4つなので、ちょうど「Perl」という文字列を生成する。
'U3'というのはUnicode文字3つなので、一文字切れて「Per」という文字列を生成する。
'U*'だと与えられたリストを的確に計って、「Perl」という文字列を生成する。
'U5'だと、リストが4要素なのに無意味に5つのUnicode文字を処理するのだが、結果的に4つだけ処理して「Perl」という文字列を生成する。
ここで、無意味に長い繰り返し回数として、500億を与えてみる。
なお、5千万とか、5億など、微妙に小さな大きすぎる数(なにそれ)を与えると、Perlが非常に遅くなるが、なんとか答えを出す。
では、どれぐらい大きな数字であれば耐えられるのだろうか。
調べると、2,147,483,640(2億1278万3640)だとエラーになるが、2,147,483,639(2億1278万3639)だとなんとか処理しようとする。
31ビットで扱える最大の数の、8ほど手前でエラーになるのである。
なぜだろうか。
ちなみにこれは、OSおよびPerlのビルドオプションで変わると思われる。
あるPerlが扱える最大の数値は、ビット演算「0のNOT」で得られるそうだ。
上の結果を見ると、ぼくのPerlは単なる数としては64ビットで計算が出来るようだ。
packの引数は32ビット符号付きの最大値から、なぜか8ほど小さい値しか使えない。
今回もスッキリしないですみません。
たとえば以下のプログラムを見てみる。
#! /usr/bin/perl実行するとこうなる。
# packUnicode.pl
use strict;
use warnings;
use utf8;
use 5.10.0;
my $packed = pack 'U4', 0x0050, 0x0065, 0x0072, 0x006c;
say "packed(4):", $packed, "!";
$packed = pack 'U3', 0x0050, 0x0065, 0x0072, 0x006c;
say "packed(3):", $packed, "!";
$packed = pack 'U*', 0x0050, 0x0065, 0x0072, 0x006c;
say "packed(*):", $packed, "!";
$packed = pack 'U5', 0x0050, 0x0065, 0x0072, 0x006c;
say "packed(5):", $packed, "!";
$ packUnicode.pl上のコードは
packed(4):Perl!<
packed(3):Per!<
packed(*):Perl!<
packed(5):Perl!
0x0050, 0x0065, 0x0072, 0x006cという4つのUnicode文字番号をUnicode化するものである。
'U4'というのはUnicode文字4つなので、ちょうど「Perl」という文字列を生成する。
'U3'というのはUnicode文字3つなので、一文字切れて「Per」という文字列を生成する。
'U*'だと与えられたリストを的確に計って、「Perl」という文字列を生成する。
'U5'だと、リストが4要素なのに無意味に5つのUnicode文字を処理するのだが、結果的に4つだけ処理して「Perl」という文字列を生成する。
ここで、無意味に長い繰り返し回数として、500億を与えてみる。
$packed = pack 'U5000000000', 0x0050, 0x0065, 0x0072, 0x006c;すると、くだんのエラーが出る。
pack/unpack repeat count overflow at /home/cf/perl/packUnicode.pl line 18.これは実行時エラーで、そのpackの直前までは正常に動作する。
なお、5千万とか、5億など、微妙に小さな大きすぎる数(なにそれ)を与えると、Perlが非常に遅くなるが、なんとか答えを出す。
では、どれぐらい大きな数字であれば耐えられるのだろうか。
調べると、2,147,483,640(2億1278万3640)だとエラーになるが、2,147,483,639(2億1278万3639)だとなんとか処理しようとする。
#$packed = pack 'U2147483640', 0x0050, 0x0065, 0x0072, 0x006c; #errこれは符号付き32ビットの最大数かと思ったが、そうでもない。
#$packed = pack 'U2147483639', 0x0050, 0x0065, 0x0072, 0x006c; #infinite
$ perl -e 'print 2 ** 31 ,"\n"'惜しい。
2147483648
31ビットで扱える最大の数の、8ほど手前でエラーになるのである。
なぜだろうか。
ちなみにこれは、OSおよびPerlのビルドオプションで変わると思われる。
あるPerlが扱える最大の数値は、ビット演算「0のNOT」で得られるそうだ。
$ perl -e 'print ~0 ,"\n"'(このエントリーを参考にさせてもらいました:Perl: 整数の最大値・最小値 - sardineの日記)
18446744073709551615
上の結果を見ると、ぼくのPerlは単なる数としては64ビットで計算が出来るようだ。
packの引数は32ビット符号付きの最大値から、なぜか8ほど小さい値しか使えない。
今回もスッキリしないですみません。