Hideki Yamane
henri****@debia*****
2010年 12月 4日 (土) 11:14:46 JST
やまねです。 twitter で教えていただいたのですが、Debian squeeze 以降の freewnn-jserver で emacs から辞書登録を行うと jserver が落ちる現象が出る場合があるようです。 原因と思われる部分についてパッチを頂きました。ご意見頂けますか? $ diff -u freewnn-1.1.1~a021+cvs20100325/Wnn/jserver/de_header.h{.original,} --- freewnn-1.1.1~a021+cvs20100325/Wnn/jserver/de_header.h.original 2004-12-30 02:45:32.000000000 +0900 +++ freewnn-1.1.1~a021+cvs20100325/Wnn/jserver/de_header.h 2010-11-28 22:16:36.000000000 +0900 @@ -548,7 +548,7 @@ extern void Get_knj2 (); extern void get_kanji_str (); extern void Get_kanji_str_r (); -extern unsigned char *kanjiaddr (); +extern unsigned char kanjiaddr (); extern int create_null_dic (); extern int create_hindo_file (); extern int input_header_jt (); 問題の調査については以下のように詳細に確認頂いています。 > ソースのあちこちに prinf を入れて、変数の値を確かめたところ、 > struct JT の maxkanjiの値が、本来は int のはずなのに、 > どうもポインタが入っているような印象を受けました。 > > 特に怪しかったのが、Wnn/jserver/jishoop.c の関数 kanjiadd の最後の > > len = (int) kanjiaddr (dest, kanji, yomi, comment); > jtl->maxkanji += len; > > という部分でしたので、この前後に printf を入れました。 > > len = (int) kanjiaddr (dest, kanji, yomi, comment); > + fprintf(stderr, "in kanjiadd: before setting jtl->maxkanji; =%d, len=%d\n", jtl->maxkanji, len); > jtl->maxkanji += len; > + fprintf(stderr, "in kanjiadd: after setting jtl->maxkanji; =%d, len=%d\n", jtl->maxkanji, len); > > すると、jserver が落ちた時に > > Nov/28/2010:19:06:26 client=kasai: JS_WORD_ADD(49): cur_clp = 0 > in kanjiadd: before setting jtl->maxkanji; =770852, len=-1220287724 > in kanjiadd: after setting jtl->maxkanji; =-1219516872, len=-1220287724 > Nov/28/2010:19:06:28 client=kasai: JS_KANREN(17): cur_clp = 0 > > のように、len がありえない値になっていました。 > 一方、きちんと登録できたときのログは次のような感じです。 > > Nov/28/2010:19:09:46 client=kasai: JS_WORD_ADD(49): cur_clp = 0 > in kanjiadd: before setting jtl->maxkanji; =770852, len=20 > in kanjiadd: after setting jtl->maxkanji; =770872, len=20 > Nov/28/2010:19:09:48 client=kasai: JS_KANREN(17): cur_clp = 0 > > そこで、len の値を決めている kanjiaddr が定義されている Wnn/etc/bdic.c を見たところ、 > > UCHAR > kanjiaddr (UCHAR* d0, w_char* kanji, w_char* yomi, w_char* comment) > { > (...) > *d0 = (UCHAR) ((UCHAR *) dest - d0); > *(d0 + 1) = state; > return (*d0); > } > > となっていました。ここでは、返り値は確かに UCHAR です。 > しかし、jishoop.c でインクルードしている Wnn/jserver/de_header.h では、 > > extern unsigned char *kanjiaddr (); > > となっているために、 > > len = (int) kanjiaddr (dest, kanji, yomi, comment); > > の部分が、コードで意図した「UCHAR を int にキャストする」ことにならずに、 > ポインタを int にキャストする結果になっています。 > > 実際、アセンブラ出力を見ると、冒頭のパッチを当てる前と後で、 > kanjiaddr の戻り値の扱いが異なっていることがわかります。 > > .LVL24: > movl %eax, 4(%esp) > leal (%ecx,%edx), %eax > movl %eax, (%esp) > call kanjiaddr > - movl %eax, %esi > - .loc 1 426 0 > - movl %eax, 12(%esp) > + .loc 1 427 0 > + movzbl %al, %esi > +.LVL25: > + .loc 1 428 0 > + movl %esi, 12(%esp) > movl 48(%ebx), %eax > movl $.LC2, 4(%esp) > movl %eax, 8(%esp) > movl stderr, %eax > movl %eax, (%esp) > call fprintf