[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[freewnn:00916] Re: dtoa SEGV



2002年09月07日(土)の05時01分に 亀井 信義 曰く:
> なんですが、 -R で作成した自分の辞書に、幾つか単語登録をしたところで、
> dtoa をやると、やはり SEGV (笑)。
> 
> 実は、こっちが元々の問題でした。
> この壊れた辞書(と思う)は、jserverで読み込むことができません。
> サーバがコケて死にます。
> 
> こっちについては継続調査です(なので、自動的に青野さんの今回の atod パッチも保留になってしまうと思うのです)。
> 
>

再発したので、もう少し追いかけてみました。
サーバ側処理迄は見てない(これはマニュアルには載ってるようですが)、
ちょっと辛いので、誰か助けて欲しいです。


再現状況は、以下の通り。

1. 正常に使用できている辞書がある(確認したのは、逆変換可能辞書)
2. タイミングは不明だが、その辞書に対して複数の単語登録を行なうと、
	どこかの時点で辞書が壊れる。
3. 但し、辞書がメモリ上のままならば、問題なく追加登録した単語を含めて使える。
4. Emacs上でのwnn-closeなどで、辞書をファイルに書き戻すと、壊れる。
5. 壊れた辞書は、jserverをクラッシュすることがある。
6. 壊れた辞書は、dtoaでダンプしようとすると、dtoaがSEGVする。
7. 壊れた辞書ファイルの漢字や読みの部分は、一見きちんと格納されている
	(ヘキサダンプして、EUC漢字コードと対応づけると、正しい)

dtoaをgdbで追っかけると、
* 正しい辞書の場合 rdtoujis に入った直後の時点、
	正確には、main()中で revdic() が完了した時点で、
		(gdb) print/x  *jt.ri2
		$173 = {next = {0xffffffff, 0xffffffff}, kanjipter = 0x0}
	となっている。

* 壊れた辞書の場合、同じ時点で、例えば
		(gdb) print/x *jt.ri2
		$175 = {next = {0x5f7fffff, 0xff1b2842}, kanjipter = 0x4d}
	このようになっている。

rdtoujis() の後続の処理で、
		jt.kanji[jt.ri2->kanjipter]
という場所から w_char 配列で、
	0	ステート
	1〜	読み
	n〜	漢字
という形でのメモリ参照を行なうことになるので、

rdtoujis() の2重 for ループにおいて、「最初の jt.ri2->kanjipter は必ず
0」という仮定がもしあるとすれば、ここが 非0 なるが故のメモリ参照エラーとなる。

※ コード中に適度に assert があるべきだと思う。


辞書のフォーマットが、分からないんですよねぇ。
特にマッピングというかファイル内オフセットと内容。
なんとか、下記程度には理解しましたが。

メモ
	    逆引き可能辞書(shyurui == WNN_REV_DICT)での構造体 JT メンバの意味
		ri1[D_YOMI]	読みの表
		ri1[D_KANJI]    漢字の表
		maxri1[D_YOMI]  読みの個数
		maxri1[D_KANJI] 漢字の個数
		kanji		漢字格納領域(w_char配列と見るべき)
		    kanji[0] ???
		    kanji[1] state; bit0 読み有り
				    bit1 漢字有り
				    bit2 コメント有り
		    kanji[2]〜kanji[m-1]    読み文字列
		    kanji[m]		    0x00
		    kanji[m+1]		    0x00
		    kanji[m+2]〜kanji[n-1]  漢字文字列
		    kanji[n]		    0x00
		    kanji[n+1]		    0x00
		ri2		辞書内エントリの表
		maxri2		辞書内エントリ数
		maxserial	同上

	    dtoa.c:rdtoujis() では、
		読み索引の順に、
		    同じ読みの漢字の順に、
			get_kanji_str()で、漢字、読み、コメントを得る。
			この段階では、各3変数の中身は big endian である。

 
-- 
	   亀井 信義