めでたく人類かマヤ暦が終了したところで、本当の人類滅亡について考察してみました。
人類ではなくて、電脳ですが、人類が滅亡する頃には電脳なしに人類がやっていけるとは思えないので。
ふと思い立って 64bit な Perl で 'print scalar localtime 0x1_0000_0000' してみたら sizeof(time_t) == 4 な環境でも 'Sun Feb7 15:28:16 2106' って出てなう
— Dan Kogai (@dankogai) December 20, 2012
GEEK以外の方のために解説すると、これ、いわゆる2038年問題です。
2038年問題 - Wikipedia1970年から2038年までしか作らなかったUNIX作った連中よりは勤勉<マヤ暦作った人は単に次のサイクルまで作るのがめんどくさかったんじゃよ
— Dan Kogai (@dankogai) December 20, 2012
2038年問題(にせんさんじゅうはちねんもんだい)は、2038年1月19日3時14分7秒(UTC、以下同様)を過ぎると、コンピュータが誤動作する可能性があるとされる年問題。
で、*nixな電脳で時刻を格納している型がtime_tなのですが、これが32bitの符号付き整数の最大値のままだと、1970年01月01日00:00:00 UTCから0x7fffFFFF秒後までしか記録できないので歴史オワタとなるというわけ。Gene Mapperにもネタとして出てきますが、2038年を待たずしてすでに先手が打たれていたので感心したわけです。
すでに対策されている代表格が、JavaScript。JavaScriptのDate型は秒ではなくミリ秒で時刻を扱うので、32bitの壁なんか生まれた時から破れてるわけです。ただし数値は64bit整数ではなく浮動小数点なので、こんな感じ。
まあこの先1万年以上大丈夫なのですが、45億年にはだいぶ足りません。
ウラジーミル△< プーチン氏 世界の終わりの日付を明らかに japanese.ruvr.ru/2012_12_20/pu-…
— Dan Kogai (@dankogai) December 20, 2012
加えてtime_tが64bitになっているのは、今のところ64bitなOSに限られているようです。
- OS X Mountain Lion @ HFS+
- FreeBSD/amd64 8.3-RELEASE @ UFS2 & ZFS
- Ubuntu 12.10/x86_64 @ EXT4
では
% touch -t 414708201632.15 future % ls -l future -rw-rw-r-- 1 dankogai dankogai 0 Aug 20 4147 future
となるのですが、
- FreeBSD/i386 7-Stable @ UFS2
- Ubuntu 12.10/i686 @ EXT4
では
% touch -t 414708201632.15 future touch: out of range or illegal time specification: [[CC]YY]MMDDhhmm[.SS]
となってしまいます。
加えて残念なことに、ファイルの日付をあまり未来に設定すると、ファイルのメタデータそのものはOKでも表示系が狂ってしまうようです。例えば
% touch eow % perl -lE 'my $when=0x7fff_ffff_ffff_ffff; say utime $when, $when,shift' eow 1
というように一見何の問題なく日付を設定しても、OS X Mountain Lionでは
% ls -l eow Segmentation fault
となってしまいますし、FreeBSD/amd64 でも
$ ls -l eow -rw-r--r-- 1 dankogai dankogai 0 Jan 0 1900 eow
という具合です。
こうなるとどこまで未来に行けるのか気になってきます。以下のPerl Scriptでチェックしてみました。
use 5.012;
my $head = 0x0000_0000_0000_0000;
my $tail = 0x7fff_ffff_ffff_ffff;
my ($when, $next);
while ($next = $head + $tail >> 1) {
last if $when == $next;
$when = $next;
# warn "$head, $when, $tail";
!!(gmtime $when) ? $head = $when + 1 : $tail = $when - 1;
}
say $when;
say scalar gmtime $when;
say scalar localtime $when;
say scalar gmtime $when+1;
ずいぶんへんてこな数字が出てきましたが、西暦2,147,483,647年は0x7fffFFFFなので、どうやら時刻を文字列に変換するgimtime()/localtime()の方に32bit問題が残っているようです。なぜ12月31日ではなく12月29日なのかも謎です。
それでもここまでの日付は、OS X Mountain Lion と FreeBSD/amd64 でタイムスタンプ押せました。
% perl -lE 'my $when=67767976233316804; say utime $when, $when,shift' eow 1 % ls -l eow -rw-r--r-- 1 dankogai staff 0 Dec 29 2147483647 eow
西暦2,147,483,647年12月29日期限のティケットを今から切っておきましょう>関係者各位
Dan the Mortal

このブログにコメントするにはログインが必要です。
さんログアウト
この記事には許可ユーザしかコメントができません。