昔の最近の出来事(2014.11)

2014/11/30

AM中に起床。

掃除したり。

先日再び使えるようになったtext-translatorですが、翻訳サイトの切り替え が簡単ではないなぁと思ったり。というのも、以前はGoogle翻訳で事足りると 思っていたのですが、意外と意味不明な翻訳になる場合が多く (参考)、 なんだか訳が分からない場合はexcite翻訳でも見てみるという事を 行うようになりました。text-translator-all-by-auto-selectionという 知っている全翻訳サイトに通した結果を得るというのもあるのですが、 それだと出すぎるのでもう少しなんとかならないか?という感じ。 贅沢な悩みですけど(^^;

MinGW gdc 2.066のtoHash()問題を調査。ずっこけの流れは以下のような感じ。

libphobos/libdruntime/object_.d
 976    override size_t getHash(in void* p) @safe pure nothrow const
 977    {
 978        assert(p);
 979        if (xtoHash)
 980        {
 981=>          return (*xtoHash)(p);
 982        }
 983        else
 984        {
 985            return hashOf(p, init().length);
 986        }
 987    }

(*xtoHash)(p)が実行されると以下に到達します。

std/typecons.d
 577        size_t toHash() const nothrow @trusted
 578        {
 579            size_t h = 0;
 580            foreach (i, T; Types)
 581=>              h += typeid(T).getHash(cast(const void*)&field[i]);
 582            return h;
 583        }

2.065以前のそれと同じく引数のpはどこかに消えて&fieldを参照していますが、 pの値と&field[i]が同じ値になるのが期待値です。ここではオプティマイズアウト されていて、&field[i]の値は参照できず。続いて以下に到達します。

libdruntime/rt/typeinfo/ti_Ag.d
121    override size_t getHash(in void* p) @trusted const
122    {
123=>      char[] s = *cast(char[]*)p;
124        size_t hash = 0;
125
126version (all)
127{
128        foreach (char c; s)
129            hash = hash * 11 + c;
130}

ここで、再びpが参照できるようになるのですが、既にpが見覚えの無い値に 変わっています。命令列実行してみると、std/typecons.dで見覚えの無い値を スタックに積んでいるので、2.065以前のそれと同じく 一体引数で渡していた ポインタはどこやったの?という感じになっているようです。

コンパイラ側の方でMinGW時は何か対応しなきゃいけない事が抜けているのだろうか? と思い、2.062ベースのフロントエンドと見比べたり。でも、違いの発見はできず。

2014/11/29

AM中に起床。

7zでのバックアップはどうにか完了。これからは時々chkdiskを実行 しよう。

日が暮れた頃に散髪に出かけたり。待ち時間にいくつかマンガ雑誌を読んだ のですが、甘い生活ってまだ続いてたんだ(シーズン2にはなってますが)とか、 島耕作って会長になってたんだとか。島耕作は本当にたまにしか読まない のですが、いつも食事して終わりってのしか読んだ事ないなぁ?と思ったり。

gdc 2.066。Fedoraの方ではなんとなく使える感じだったので、 MinGWの方でリンクに失敗する件を調べたり。すると、Fedoraの方 では関数シンボル名が「_D2...」となっていたり。MinGWの方では 「__D2...」となっていて、そのせいでMinGWの方ではリンクができない ものと推測。で、-Sでアセンブラコードを出力した後、 シンボル名を__D2...から_D2...に手で書き換えてアセンブルし、 libdruntimeを生成してみたところリンクできました。 まぁ動かんだろうなと思いつつ実行してみたところ、何気に動いて しまったので驚いてみたり(^^;;;

$ cat iam.d
import std.stdio;
import std.string ;

int main()
{
  version( GNU     ) writef("I am GNU\n"    ) ;
  version( Unix    ) writef("I am Unix\n"   ) ;
  version( linux   ) writef("I am linux\n"  ) ;
  version( Windows ) writef("I am Windows\n") ;
  version( MinGW   ) writef("I am MinGW\n"  ) ;
  version( MinGW32 ) writef("I am MinGW32\n") ;
  version( MinGW64 ) writef("I am MinGW64\n") ;
  version( cygwin  ) writef("I am cygwin\n" ) ;
  version( Win32   ) writef("I am Win32\n"  ) ;
  version( Win64   ) writef("I am Win64\n"  ) ;
  version( Posix   ) writef("I am Posix\n"  ) ;
  version( X86     ) writef("I am X86\n"    ) ;
  version( X86_64  ) writef("I am X86_64\n" ) ;

  return(0) ;
}

$ gdc -v
Using built-in specs.
COLLECT_GCC=C:\MinGW\gdc031_2066_50x\bin\gdc.exe
COLLECT_LTO_WRAPPER=c:/mingw/gdc031_2066_50x/bin/../libexec/gcc/mingw32/5.0.0/lto-wrapper.exe
Target: mingw32
Configured with: ../gcc-5-20140831/configure --build=mingw32 --with-arch=i686 --enable-languages=c,c++,d,lto --prefix=/mingw/gdc031_2066_50x --enable-threads --disable-nls --enable-sjlj-exceptions --disable-bootstrap --disable-gcov-tool
Thread model: win32
gcc version 5.0.0 20140831 (experimental) (GCC)

$ gdc iam.d

$ ./a.exe
I am GNU
I am Windows
I am MinGW
I am Win32
I am X86

マジか。リンクできないという関数について、関数呼び出しを行っている thread.dでは、

    alias rt_tlsgc_init = externDFunc!("rt.tlsgc.init", void* function());

というようなテンプレートを使って、何故かrt.tlsgc.init(他にもあり)の 含まれるソースをimportせずに関数呼び出しを行おうとしています。このexternDFuncと いうテンプレートが生成するシンボル名がマズいのだろうと推測したのですが、 コードを読んでも何やってんだかよく分からなかったり。
TANEはいまひとつテンプレートを使いこなせないのですが、その原因の一つに どう展開されているのかを見る術が無いというのが挙げられます。C言語では プリプロセッサを使う場合でも、-Eでどのように展開されたかを調べる 術があるのですが、そういうのがgdcには無くていきなりアセンブラコードが 出てくるものですから、どうも慣れないと言いますか。オリジナルのDMDは アセンブラコードも出せないようなので、これ、コンパイラがバグってたら どうやって調べてるんだ?と思う所はあります。

さておき、そもそも2.066をビルドしたのは、Segfaultでずっこける原因が分からず、 2.065→2.066で大幅にlibphobos/libdruntimeのコードが変わっていたので、自然に 直ったりしていないか?と期待したからでした。 で、件のずっこけコードをコンパイル&実行してみたところ やっぱりダメ。

$ cat mingwgdcfailed_test.d
import std.regex;

void main()
{
  OBJ3D o = new OBJ3D() ;
  return ;
}

class OBJ3D
{
  this(){
    regex( r"^mtllib\s+","") ;
  }
  void print(){
  }
}

$ gdc mingwgdcfailed_test.d

$ gdb -q a.exe
Reading symbols from C:\cygwin\home\TANE\develop\dlang\test\dmd2065gcc490\a.exe...done.
(gdb) run
Starting program: C:\cygwin\home\TANE\develop\dlang\test\dmd2065gcc490\a.exe
[New Thread 7640.0x1e8c]

Program received signal SIGSEGV, Segmentation fault.
0x0040d19b in rt.typeinfo.ti_Ag.TypeInfo_Aa.getHash() (this=..., p=0x51f440)
    at ../../../../gcc-5-20140831/libphobos/libdruntime/rt/typeinfo/ti_Ag.d:129
129                 hash = hash * 11 + c;
(gdb) where
#0  0x0040d19b in rt.typeinfo.ti_Ag.TypeInfo_Aa.getHash() (this=...,
    p=0x51f440)
    at ../../../../gcc-5-20140831/libphobos/libdruntime/rt/typeinfo/ti_Ag.d:129
#1  0x004ba067 in std.typecons.__T5TupleTAyaTAxaZ.Tuple.toHash() ()
#2  0x00405453 in object.TypeInfo_Struct.getHash() (this=..., p=0x28fb48)
    at ../../../../gcc-5-20140831/libphobos/libdruntime/object_.d:981
#3  0x00415bc6 in _aaGetX (
    aa=0x45aa3f <std.functional.__T7memoizeS83_D3std5regex18__T9regexImplTAyaZ9regexImplFNfAyaAxaZS3std5regex12__T5RegexTaZ5RegexVki8Z.memoize()+367>,
    keyti=..., valuesize=5370944, pkey=0x4c)
    at ../../../../gcc-5-20140831/libphobos/libdruntime/rt/aaA.d:170
#4  0x0028fb88 in ?? ()
(gdb)

ずっこけ方は違うのですが、やっぱりtoHash()に関する何かでダメという気が。

手持ちのWindowsアプリコードをコンパイルしてみたところ、一応起動できる のですが、特定のコードを通るとtoHash()問題が発動するもよう。 2.065よりも不安定かも。

そういえば、何故か使えなくなっていた text-translatorというWeb翻訳 elispですが、こちらのText Translator というEmacsWikiサイトのダウンロードで指されるcode.launchpad.netのページ でメンテナンスされていたようで、今年の8月付けのファイルが 公開されていました。こちらのサイトはブラウザからアーカイブを取得 する事ができないようなので、bzrコマンドで一式ダウンロード してみたり。で、新しいバージョンにしてみた所、問題無く 使えました(^o^)。
因みに、text-translatorが使えない間は google-translatorを使用 していたのですが、google-translatorは決まった方向にしか翻訳できない (target-languageが固定される)のが難点でした。

2014/11/28

遅めに帰着。

2日がかりでchkdisk実行の結果、不良セクタの無い状態に。 そんな訳で7zで残りのディレクトリをバックアップ開始。 うまくいくかはまだ分からず。今のPCは買った時からディスクが 怪しい節があったのですが、不良セクタって徐々に増えるもの なのだろうか?と思ったりも。

あまりの眠さに急速停止。

2014/11/27

遅めに帰着。

先日のcore.threadが見つからない件は、libdruntime/core/thread.dを 手でコピーすれば大丈夫そうでした。一応、使えそうな感じです。 いつも思うのですが、クリーンインストールできる事を試していない のかしら?

2014/11/26

遅めに帰着。

Fedoraの仮想ディスクを拡張。物理的に増やすのに比べると随分簡単だなぁ と思ったり。

gdc 2.066版をビルド。エラー無くビルドできたのでmake install してみたり。hello worldレベルの極簡単なコードはコンパイル&実行できました。 しかし、ちょっとしたコードで以下のようなエラー。

$ gdc -O2 -I. -c main.d
/usr/local/gdc_2066_50x/include/d/5.0.0/std/process.d:2966:8: error: module thread is in file 'core/thread.d' which cannot be read
 import core.thread;
        ^
import path[0] = /usr/local/gdc_2066_50x/include/d/5.0.0/x86_64-unknown-linux-gnu
import path[1] = /usr/local/gdc_2066_50x/include/d/5.0.0
import path[2] = /home/tane/develop/dlang/fractal

確かに、どこにも無くてエラーメッセージ通りなのですが、これどうなってんの? って感じ。まだマージできていないという事か?

2014/11/25

遅めに帰着。

先日の7zで圧縮時にCRCエラーになる原因判明。HDDの一部に不良セクタ が存在していて、ファイルが読めなかったのが理由だった模様。 ファイルシステムチェックでいくつかサルベージor削除されたファイルが あったようでひとまず修復。結局昨日の夜から10時間以上かかった模様。 で、7zで圧縮を試してみたのですがまだダメ。むーん。

gdcの2.066。リンクができない件をFedoraではどうなるか試そうとしたの ですが、VMware上の仮想ディスク容量が足りなくてビルドに失敗。

2014/11/24

昼過ぎ起床。

7zを使ってファイルのバックアップを試みているのですが、何故か Windows用のGUI版を使うと圧縮途中でCRCエラーを検出しました みたい なダイアログが開いて停止してしまいます。すぐにエラーが出るなら ともかく、数時間実行した途中でずっこけるものですから、時間と電気 だけが無駄に消費されてたり。Webで検索するも圧縮時に同様の症例が 見当たらず。そもそも圧縮時のCRCエラーってなんだ?
結局、Cygwin(32bit)の7zでもメモリが足りなくなってかエラーで ずっこけたので、仕方なく tar.xz で我慢する事に。

gdcの2.066作業中(?)版のビルドを試してみる事にしたり。 gccはスナップショットのgcc-5-20140831ってのを使用。で、ビルドを 開始してみるもコンパイルエラー。ftw.hってヘッダファイルが無いと いう事だったのですが、ftwって何?ってのから始めて、最終的に gcov-toolのビルドをdisableにするのが良いという事に至ったり。 こちらのパッチ を適用すると--disable-gcov-toolというconfigureオプションが使用 できるようになり、gcov機能のソースから参照しているftw.hも不要 になるという展開です。因みにftwは「file tree walk」で、 ディレクトリパスを辿るライブラリらしい。

途中、怪しい対応でどうにかビルドできたものの、インストールして 使ってみたらリンクできなくてどうにもならなかったり。 libgdruntimeとlibgphobos2とが分離したようですが、libgdruntimeが リンクされていないのが原因の模様。手動でリンクを試みるも 何故か駄目。うーむ。

2014/11/23

AM中に起床。

洗濯したり掃除したり。

x86の関数呼び出し規約(ABI)がよく分かっていなかったので調べたり。 基本はスタックを介して値渡しをする感じ (参考Wikipedia)。 レジスタ渡しで大抵の事は足りるPowerPCとは大分様子が違います。

$ cat -n test3.d
     1  import std.stdio;
     2
     3  void main()
     4  {
     5    void* p=cast(void*)(0x12345678) ;
     6    int   q=0xaaa5555 ;
     7    TestClass o = new TestClass() ;
     8
     9    o.test(p,q);
    10
    11    return ;
    12  }
    13
    14  size_t testfunc(in void* p, int q){
    15    return(-1) ;
    16  }
    17
    18  class TestClass
    19  {
    20    size_t function(in void*, int) tf ;
    21
    22    this(){
    23      tf = &testfunc ;
    24    }
    25
    26    size_t test(in void* p, int q){
    27      return (*tf)(p,q);
    28    }
    29  }

の27行目でtestfunc()をcallする直前のレジスタ状態が以下。

=> 0x401351 <_D5test39TestClass4testMFxPviZk+33>:	call   *0x8(%ebx)
9: /x $eip = 0x401351
8: /x $edi = 0x40f157
7: /x $esi = 0x40f1d4
6: /x $ebp = 0x28fbe8
5: /x $esp = 0x28fb70
4: /x $ebx = 0xd61fe0
3: /x $edx = 0x52a2f8
2: /x $ecx = 0xd61fe0
1: /x $eax = 0x12345678
(gdb) x/16x $esp
0x28fb70:	0x12345678	0x0aaa5555	0x0000000c	0x0052a320
0x28fb80:	0x004157e0	0x004c6e80	0x00000001	0x00d61fe0
0x28fb90:	0x0028fc50	0x0040f1d4	0x0028fc50	0x004013bc
0x28fba0:	0x12345678	0x0aaa5555	0x00000000	0x00523d00

この状態でcall命令を実行すると、

=> 0x401310 <_D5test38testfuncFxPviZk>:	mov    $0xffffffff,%eax
9: /x $eip = 0x401310
8: /x $edi = 0x40f157
7: /x $esi = 0x40f1d4
6: /x $ebp = 0x28fbe8
5: /x $esp = 0x28fb6c
4: /x $ebx = 0xd61fe0
3: /x $edx = 0x52a2f8
2: /x $ecx = 0xd61fe0
1: /x $eax = 0x12345678
(gdb) x/16x $esp
0x28fb6c:	0x00401354	0x12345678	0x0aaa5555	0x0000000c
0x28fb7c:	0x0052a320	0x004157e0	0x004c6e80	0x00000001
0x28fb8c:	0x00d61fe0	0x0028fc50	0x0040f1d4	0x0028fc50
0x28fb9c:	0x004013bc	0x12345678	0x0aaa5555	0x00000000

てな感じになります。戻る命令位置(callの次の命令位置なので0x401351+3を指している)、 1番目引数、2番目引数という感じで並んでいます。 関数の戻り値は %eax レジスタに入るという事なので、このコードでは 即値で0xffffffff(==-1)を %eax にロードする感じになってます。

これを踏まえて、件のSegfaultコードを見てみる事にしてみたり。

libphobos/libdruntime/object_.d :
 :
971    override size_t getHash(in void* p) @safe pure nothrow const
972    {
973        assert(p);
974        if (xtoHash)
975        {
976            return (*xtoHash)(p);
977        }
978        else
979        {
980            return hashOf(p, init().length);
981        }
982    }

このコードの976行目でcallする直前の変数pの値とスタックの状態が以下。

(gdb) p p
$2 = (const void * const) 0x28f7d4

=> 0x412f9f <_D6object15TypeInfo_Struct7getHashMxFNaNbNfxPvZk+146>:	call   *%eax
9: /x $eip = 0x412f9f
8: /x $edi = 0x28fb40
7: /x $esi = 0x1a
6: /x $ebp = 0x28f678
5: /x $esp = 0x28f640
4: /x $ebx = 0x412f0d
3: /x $edx = 0x28f7d4
2: /x $ecx = 0x56f800
1: /x $eax = 0x42974a
(gdb) x/16x $esp
0x28f640:	0x0028f7d4	0x0000001a	0x00000020	0x00c45fc0
0x28f650:	0x0056d3e0	0x00000000	0x00000000	0x0045a0b4
0x28f660:	0x0000001a	0x0028fb40	0x0028f688	0x0056f800
0x28f670:	0x00412f0d	0x0000001a	0x0028f6b8	0x00413cd6

引数としているポインタの値(0x0028f7d4)がスタックに積まれています。 ここでcallを実行すると次のようになります。

まず元のコードは以下の通り。

libphobos/src/std/internal/uni.d
 :
408    size_t toHash() const pure nothrow @safe
409    {
410        size_t hash = 5381+7*ivals.length;
411        if(!empty)
412            hash = 31*ivals[0] + 17*ivals[$-1];
413        return hash;
414    }

スタックの状態は以下の通り。

=> 0x42974a <_D3std8internal3uni12CodepointSet6toHashMxFNaNbNfZk<:	push   %ebp
9: /x $eip = 0x42974a
8: /x $edi = 0x28fb40
7: /x $esi = 0x1a
6: /x $ebp = 0x28f678
5: /x $esp = 0x28f63c
4: /x $ebx = 0x412f0d
3: /x $edx = 0x28f7d4
2: /x $ecx = 0x56f800
1: /x $eax = 0x42974a
(gdb) x/16x $esp
0x28f63c:	0x00412fa1	0x0028f7d4	0x0000001a	0x00000020
0x28f64c:	0x00c45fc0	0x0056d3e0	0x00000000	0x00000000
0x28f65c:	0x0045a0b4	0x0000001a	0x0028fb40	0x0028f688
0x28f66c:	0x0056f800	0x00412f0d	0x0000001a	0x0028f6b8

戻りアドレス(0x00412fa1)と引数のポインタ(0x0028f7d4)はちゃんと スタックに積まれていますが、そもそも関数の引数定義が呼び出し元と 違っています。普通に考えて、これダメな奴じゃね?という感じなのですが、 DMD2.062ベースの頃から変わっていないコードです。ここがヘンテコなコードだと 言ってる理由です。で、これだけ見ても呼び出し元の *p値(0x0028f7d4)と &ivals値が同じになる根拠は全く無いのですが、DMD2.062ベースとかでは このコードで何故か&ivals値が*p値(0x0028f7d4)と同じになっていて、 Segfaultせずに動いています。

で、ややこしいのは、じゃぁ uni.dのtoHash()の引数を定義すれば いいんじゃね?と思って「toHash(in void* p)」てな感じに取り合えず 書き換えてコンパイルしてみたところ、今度はobject_.dのxtoHashの値が 何故か0になってしまい、974行目の条件が成立せず全く動きが変わってしまいます。 そして最終的にGCがぶっ壊れてしまうようです。見た目から動きが読み取れない ようなコードはどうにかならないかしら?と思ったり。

オリジナルDMDのphobosのマスターブランチ(2.067のベータ相当)では、 std/internal/uni.dというファイル自体が無くなっていて、作りが大分 変わっているようです。DMD2.066から無くなったようなので、gdcに 来るのを(現在まだmasterには来ていない)待った方が良いか?

久しぶりにPS4の「TRIALS FUSION」を起動してみたり。 Ice Climbという、ミスらずにどこまで登れるかというスキルゲームの 1位に新しいリプレイデータが上がっていたり。でも、 もうあと一息って所で終了。当初はこのスキルゲーム、割とすぐに 登り切ったデータばかりになって、タイム勝負になるのかな? と思っていたのですが、なかなか登り切る人が出てこないのは 意外に思いました。因みに、Xbox360版の登り切ったリプレイ 動画を見たのですが、 最初のランキング一覧から察するに、この時点でも(2014/7/20付け) 登り切ったのはこのデータだけだったようですね。

2014/11/22

AM中に起床。休出。

ちょっとsedについて調べたとき、 GNUのマニュアルの存在を知ったり (sed, a stream editor)。 wcとかuniq相当の動作をsedでも書けるというのを知り、どんだけ!? と思ったり。

gdc調査。命令単位でステップ実行してみたところ、 やっぱり違う値を参照している感じでした。違う書き方で 同じ事をする方法があれば試せる所なのですが、ヘンテコな コードなのでどうするのが良いかよく分からず。

メルセデスのCMでマリオカートコラボバージョンがありますが、 ピーチ姫バージョンって1回しか観たことないなぁ?と思ったり。

2014/11/21

遅めに帰着。

「千と千尋の神隠し」の終わりかけから見たり。 そういや赤くないなぁ?と思ったり。

gdc調査。やっぱり関数の引数受け渡しのアセンブラコードが おかしな事になっているような気がするなぁ?

2014/11/20

遅めに帰着。

先日のビルドはひとまず完了。で、使ってみたところやはり Segfaultが再現するもよう。ベースgccはあまり関係無く、 DMD2.065マージに問題があるという事か?

2014/11/19

遅めに帰着。

gdc調査。やっぱりphobosのコードがこれで動く理由が 分からない。

gcc-4.8.x+DMD2.065ブランチのビルドを試してみる事にしたり。 起きている間に終わらず。

2014/11/18

少し遅めに帰着。

gdc調査。括りだしを試みるも再現できず。

2014/11/17

遅めに帰着。

gdc調査。コードを見るもこれであのように動くのか、やっぱり よく分かりません。

2014/11/16

昼過ぎ起床。

掃除したり洗濯したり。

gdcずっこけ調査(ずっこけるのは正確にはgdcで生成した実行ファイルですが)。 怪しいソースだけgcc-4.8.0+DMD2.062ベースのgdcでコンパイルすれば大丈夫じゃね? と思い試してみたところ、もっと関係無いところでずっこけたり。失敗。

もそもそと追いかけ。どうも思っている動きと違う気がしたり。ずっこける 少し前から辿ると、

libphobos/libdruntime/object_.d:
    override size_t getHash(in void* p) @safe pure nothrow const
    {
        assert(p);
        if (xtoHash)
        {
            return (*xtoHash)(p);
        }
        else
  :

ここで、「(*xtoHash)(p)」を通ると、

libphobos/src/std/internal/uni.d:
    size_t toHash() const pure nothrow @safe
    {
        size_t hash = 5381+7*ivals.length;
        if(!empty)
            hash = 31*ivals[0] + 17*ivals[$-1];
        return hash;
    }

に到達します。このとき、「&ivals(ivalsの格納場所)」が呼び出し元の 「p」と同じ値であるのが正解なのですが、そうなっていないのが、 ずっこけの直接の原因です。でも、これだけを見ると関数呼び出し時に引数を 渡している訳ではなくて、どこかずっと前から「&ivals」と「p」は 同じである事が保証されているハズなのが、そうなっていないだけ という感じになっている気がしたり。そんな訳で元が妙なコードなもんですから、 どうすりゃ最小コードを括り出せるのかが分からないというのが今の状況。

「ピアノの森(25)」。次が最終巻。

2014/11/15

AM中に起床。休出。

gdcずっこけを調べたり。Fedoraでビルドしたgcc-4.9.0+DMD2.065ベースのgdcの 命令列(-m32の命令列)を調べたり。すると、先日調べた時の gcc-4.8.0+DMD2.062ベースのMinGW gdcとほぼ同じ命令列になっていたり。 何故 MinGWのgcc-4.9.0+DMD2.065ベースgdcだけちょっと違っているのかが カギとなるようです。
如何せんPhobosの中のコードなので、関数呼び出しがおかしくなる 再現コードをくくり出せれば良いのかも。ちょっとヘンテコな 書き方なのでどうしたもんか。

2014/11/14

遅めに帰着。

gdcのビルド。ちょっと手直しが必要な点があったのを色々 忘れていてやり直したりしてたら終わらず。

ひとまずビルドできたのでmake installして、先日から調べている ずっこけ再現コードをコンパイルしてみたのですが、やっぱり Segfaultで落ちました。ずっこけ方も同じなので、まぁ 特に何もしてなければ直ったりはしないだろうなという結果でした。

2014/11/13

遅めに帰着。

あまりの眠さに急速停止。

2014/11/12

遅めに帰着。

ずっこけるgcc-4.9.0+DMD2.065ベースgdcと、ずっこけないgcc-4.8.0+DMD2.062ベースgdcとで 再現コードの動きを見比べてみたり。動き自体は同じなのですが、 gcc-4.8.0+DMD2.062ベースの方は問題のポインタ渡しのコードはうまく動いて います。命令単位実行してみると大分異なるコードを実行していたり。

----------------------------------------------------------------------------
gcc-4.8.0+DMD2.062ベース命令列
00404d8c <__D6object15TypeInfo_Struct7getHashMxFNaNbNfxPvZk>:
  404d8c:       53                      push   %ebx
  404d8d:       83 ec 18                sub    $0x18,%esp
  404d90:       8b 54 24 20             mov    0x20(%esp),%edx
  404d94:       8b 5c 24 24             mov    0x24(%esp),%ebx
  404d98:       8b 42 18                mov    0x18(%edx),%eax
  404d9b:       85 c0                   test   %eax,%eax
  404d9d:       74 0d                   je     404dac <__D6object15TypeInfo_Struct7getHashMxFNaNbNfxPvZk+0x20>
  404d9f:       89 5c 24 20             mov    %ebx,0x20(%esp)
  404da3:       83 c4 18                add    $0x18,%esp
  404da6:       5b                      pop    %ebx
  404da7:       ff e0                   jmp    *%eax →ここで 0x00413228にjump。スタックにポインタ値は保持

00413228 <__D3std8internal3uni12CodepointSet6toHashMxFNaNbNfZk>:
  413228:       56                      push   %esi
  413229:       53                      push   %ebx
  41322a:       83 ec 14                sub    $0x14,%esp
  41322d:       8b 74 24 20             mov    0x20(%esp),%esi
  413231:       8b 1e                   mov    (%esi),%ebx  →ここで%esi にポインタ値が渡り、正しくポインタ値として使用されている


----------------------------------------------------------------------------
gcc-4.9.0+DMD2.065ベース命令列
00404620 <__D6object15TypeInfo_Struct7getHashMxFNaNbNfxPvZk>:
  404620:       83 ec 1c                sub    $0x1c,%esp
  404623:       8b 41 18                mov    0x18(%ecx),%eax
  404626:       85 c0                   test   %eax,%eax
  404628:       74 16                   je     404640 <__D6object15TypeInfo_Struct7getHashMxFNaNbNfxPvZk+0x20>
  40462a:       8b 54 24 20             mov    0x20(%esp),%edx
  40462e:       89 14 24                mov    %edx,(%esp)
  404631:       ff d0                   call   *%eax  →ここで 0x0041c310をcall。このとき  %edi にポインタ値を保持してるのかと思いきや.....

0041c310 <__D3std8internal3uni12CodepointSet6toHashMxFNaNbNfZk>:
  41c310:       56                      push   %esi
  41c311:       53                      push   %ebx
  41c312:       89 ce                   mov    %ecx,%esi  この時点で何故か %ecx をポインタと思っているようだ
  41c314:       83 ec 14                sub    $0x14,%esp


----------------------------------------------------------------------------

コンパイラがバグっている疑いが濃厚。

ここしばらくmasterブランチに更新が無かったgdcですが、先日、 6月以降のmasterブランチの更新が、gcc-4.9.0+DMD2.065ベースブランチと gcc-4.8.0ベースブランチにDMD2.065マージされたので、再ビルドを試して みるか。

2014/11/11

遅めに帰着。

先日のコードをFedoraのgdcでコンパイル&実行してみたのですが 特に問題無し。MinGWとFedoraの両方でデバッガを使って、 同じ箇所にブレークポイントを設定したりステップ実行しながら 変数の値を観察した結果、動きが違っている箇所があったり。 関数の引数が正しく伝わっていない模様。

そういえば、Emacs-24.4で、「C-x SPC」は矩形選択開始に 割り当てられるようになったのですが、Emacs-24.3以前ではgdbを使う為の gud(grand unified debugger)でブレークポイントを設定するバインドが 「C-x SPC」になってました。24.4では「C-x C-a C-b」を使う必要 があるようです。因みに、24.3以前から「C-x C-a C-b」"も"ブレークポイント の設定だったようです。単によく使うから「C-x SPC」がいいんじゃね? って感じで割り当てられていたのかも。

2014/11/10

遅めに帰着。

そういえば、gdcprojectページの ダウンロードページにMinGWの DMD2.065+gcc4.9.0ベースの実行バイナリが 置かれているのを知ったり。 以前、gcc4.9.0ベースのMinGWビルド を試してみたのですが、手持ちコードの一部が std.regexの中でSegfaultする 原因が判らず、使用不可状態のまま今に至っています。 そんな訳で、コンパイル済バイナリだとうまく動いたりしないか?というのを 確認してみようと思った次第。で、結論から言うと全く同じ箇所でSegfaultしたり。うーむ。

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 2108.0x1e68]
0x004a75c5 in std.internal.uni.CodepointSet.toHash() (this=...)
    at /home/build/tmp/native_build/.build/src/gcc-4.9.0/libphobos/src/std/internal/uni.d:412
(gdb) 412       /home/build/tmp/native_build/.build/src/gcc-4.9.0/libphobos/src/std/internal/uni.d: No such file or directory.

(gdb) where
#0  0x004a75c5 in std.internal.uni.CodepointSet.toHash() (this=...)
    at /home/build/tmp/native_build/.build/src/gcc-4.9.0/libphobos/src/std/internal/uni.d:412
#1  0x0046fe43 in object.TypeInfo_Struct.getHash() (this=..., p=0x1601e984)
    at /home/build/tmp/native_build/.build/src/gcc-4.9.0/libphobos/libdruntime/object_.d:976
#2  0x00493ec6 in _aaGetX (aa=0x49d506 <std.regex.getTrie()+262>, keyti=...,
    valuesize=6464448, pkey=0x14)
    at /home/build/tmp/native_build/.build/src/gcc-4.9.0/libphobos/libdruntime/rt/aaA.d:170
#3  0x1601ea38 in ?? ()
#4  0x0060d540 in ___s.4035 ()
#5  0x00000000 in ?? ()

最小コードで再現できれば良いのですが出来てないので困った感じ。 本格的に調べた方が良いかもなぁと思い始めたり。

ひとまず、以下で再現する所までは絞れてみたり。

import std.regex;

void main()
{
  OBJ3D o = new OBJ3D() ;
  return ;
}

class OBJ3D
{
  this(){
    regex( r"^mtllib\s+","") ;
  }
  void print(){
  }
}

ポイントは「^mtllib\s+」を「^mtllib」にすると大丈夫そうな所。 なんかこれだけ見ると std.regexがバグっているだけのような気も。 でも、phobosのmasterブランチはstd.regex.packageというのに置き換わっていて、 新しいのと比べる事ができなくなっている予感。

2014/11/09

AM中に起床。

掃除したり録画消化したり。

doc-viewでPDF閲覧の件。先日、文字列サーチのハイライトは できないと書いたのですが、 pdf-toolsなる 外部ツールでそれが可能になるらしい。Cygwinでのビルドを 試みたのですが、なんかキャストがらみで色々コンパイルエラーが でるのを直してどうにかインストールしてみたものの、 使ってみると無言でEmacsごとお亡くなりになるようです。 残念。うまく動くと こんな感じ の事ができるらしい。

pdf-toolsでEmacsごとお亡くなりになる原因を調べてみたり。 どうやらImageMagicのcygMagickCore-5.dll内でSegfaultとなっているもよう。 含んだつもりはなかったのですが、configure時にwithoutで明に 外していないと自然に含まれる模様。 ImageMagicを含むと24.3の頃は明らかに 不調になったのですが、 24.4では大丈夫そうだったので気づきませんでした。 で、--without-imagemagickでEmacsを再ビルド。そしてpdf-toolsを 使ってみるとうまく動きました(^^)v。

pdf-tools on Emacs

スナップショット画像の通り、日本語文字列もisearchライクに サーチ&ハイライトできます。素晴らしすぎる。 そんな訳で、11/9時点のmasterブランチに対して コンパイルエラーするのを直したパッチを置いて みます(pdf-tools.patch.xz)。 ビルドにはPoppler というPDFレンダリングライブラリが必要ですが、Cygwinパッケージ のをインストールしておけばOKだと思います。
それにしても、epdfinfoのオリジナルソースは、.cファイルにも関わらず C++のbool型を使ってたりして、gccだと 絶対にコンパイルが通らないように 思うのですが、作者様は一体どうやって通しているんだろう?と思ったり。

2014/11/08

昼過ぎ起床。なんか寒い。

Emacsでdoc-viewという標準ELISPを使用してPDFファイルを見る事が できます。ただ、GhostScriptを使ってPNGファイルに変換したものを表示 するのですが、ぶっちゃけ変換が遅いので見ようと思えば見られるね という程度でした。 で、24.4ではGhostScriptの他に MuPDFというPDFレンダラを使用 できる事を知ったり。MuPDF自体は軽量のPDFビュアとして Windowsバイナリも存在しているようです。さておきソースを ダウンロードしてCygwinビルドしてみたり。特につっかかる 事無くビルド完了。で使ってみるとレンダリングが速くて(約2倍) 良い感じに閲覧できたり。ただ、文字列サーチとかを行っても ハイライトはされません。一度画像に変換している以上どうにも ならない感じかも。

2014/11/07

遅めに帰着。

Web巡回して終了。

2014/11/06

遅めに帰着。

もそもそと実験。

2014/11/05

遅めに帰着。

JavaScript。イマイチプログラムの実行順序がよく判らなかったり。
先日の画像描画順序はロードが完了してないのに描画しようとして 描けたり描けなかったりするというのがなんとなく判ったので、 Webのコードを参考にロードが完了したら描画を行うように考えて みました。で、以下のように書いてみた訳ですが、

 1        var filelist = [ "b18.jpg", "b17.jpg" ] ;
 2        var imglist  = [] ;
 3
 4        function loadImages(){
 5            var img = new Image();
 6            img.addEventListener(
 7                'load',
 8                function(){
 9                    imglist.push(img);
10                    if(filelist.length==imglist.length){
11                    }else{
12                        loadImages();
13                    }
14                },
15                false);
16            img.src = filelist[imglist.length];
17            confirm("imgload" + imglist.length);
18        }
19        loadImages() ;
20
21        confirm("start" + imglist.length);
22        for(var i in imglist){
23            context.drawImage(imglist[i],100+i*50,100+i*50) ;
24        }
25        confirm("end" + imglist.length);

デバッグで入れたconfirm()の実行順序が、 17行目(1回目)、17行目(2回目)、21行目、25行目 となるのを期待した のですが、実際には17行目(1回目)、21行目、25行目、17行目(2回目) という順序で実行されて、はぁ? ってな感じに。 何か根本的な所を勘違いしているのかしら?

2014/11/04

遅めに帰着。

JavaScriptの調べ事。canvasを使う実験を行っていて、何故かうまく描画 されなくて順に調べていくと、何故かcanvasタグのidに"canvastest" を指定すると描画されなくてハマりました。"canvastes"だったら OKだったりするのですが、"canvastest"って何かの予約語なの? あと描画順序がイマイチよく判らなかったり。

2014/11/03

AM中に起床。

プロ遊の下に「Emacs Org-modeの覚え書き」 という文書を追加しました。御参考まで。

Webを散策していて、SVGをWebブラウザでアニメーション表示させる事が 最近では割と簡単にできるようになってるのを知ったり。 ただ、アニメーションをさせるにはいくつか方法があって、 方法によっては表示できないブラウザがあったりする模様。 ブラウザも色々レンダリングできなくてはならなくて 大変だなぁ?と思ったりも。

SVGのWebアニメーションについてもそもそと実験。 Inkscapeで作成したオブジェクト群の一部をJavaScriptで動かすという 方法を試してみたり。html内に埋め込まれたsvgデータは、 約60fpsで毎回レンダリングされるので、フレーム毎にオブジェクトの 座標や頂点を変化させればアニメーションしているように見えると いう感じに理解してみたり。ただし、Inkscapeとブラウザとでは 座標系が違っている為、回転とかは予め計算しておかないと思った位置 を中心に回せないという感じのようです。
で、雰囲気はなんとなく判ったのですが、IEとその他(ChromeとFireFox) とで決定的な違いがあってどうすりゃいいの?と思ったり。 IE以外のブラウザでは、SVGタグのサイズ要素に対して、中に存在する 一部のオブジェクトを拡大してもサイズでクリッピングされるのですが、 IEではクリッピングされずにブラウザページを全画面扱いで表示 してしまいます (SVGアニメテストHTML)。うーむ。

2014/11/02

昼頃起床。

掃除したり洗濯したり。

数日の試用期間を経たので、Cygwinのパッケージアップデートで Emacsを24.4に上げてみたり。そしてIME対応版に即差し替え。 普段手を入れて使っているものを上書きインストールするのは 何かと手がかかって大変です。 そうしないと用事にならないので仕方ありませんが。

調べ事をしていたら、 「graph Hatsune miku curve」 なるものの存在を知ったり。数式で初音ミクを描いたというものですが、 なんかスゲェ。

もそもそと作文。

2014/11/01

AM中に起床。

NyanModeの更新ツリーを見てみたり。1年ほど前に 初めて知った時は ほぼ開発は終わり、あまり更新はされていない感じかな?と 思っていたのですが、その後もちょくちょく更新されていたようです。 -nw対応されたのは今年の夏くらいで、どうやら日本の人による Pull Requestだったようです。UTF-8表示のターミナルだと 日本語圏外の人でも容易に表示可能になるのでしょうか。

nyan-mode console

所で、最後の奴とかは途中に「"( >ワ三<  )"」 てのが入ってるのですが、これって表現正しいの?と思ったり。 元々、「(三ワ三)」というベースの顔に対して、ウインクやらスピード 線を入れている感じなのかな?と思うので、

"(>ワ<三   )"
"( >ワ三<  )" → "( >ワ三   )"
"(  >三ワ< )" → "(   三ワ< )"
"(   三>ワ<)"

という感じじゃないかと思ったりも。TANE自身、ベースの「(三ワ三)」が 顔と認識できるまで時間がかかりましたが(^^;

調べ事をしていて見つけた「 MSX - Space Harrier 」という動画。すげぇ。

おすそ分けで柿をもらったのですが、皮を剥いて食べ終わった後に 「あれ?種が無かったなぁ?」と思ったり。 Webで調べてみたところ、恐らく「平核無(ひらたねなし)」という 奴だったと思われます。本来は渋柿のようですが、 渋抜きすることで甘くなるそうな。こんなのがあるとは 知りませんでした。

そういえば、ビルドしたEmacs-24.4は -nwも動作するのですが、 その場合でもinput-methodが W32-IMEになってしまいます。 -nw時はanthyに切り替えたいなぁと思ったので方法を探ってみたところ、 window-systemという変数を評価するのが良いらしい。 (eq 'w32 (window-system))てな感じでtならw32-imeの設定を、そうで なければanthyをという感じで切り替えてみました。


TOP PREV