[Message Prev][Message Next][Thread Prev][Thread Next][Message Index][Thread Index]

[MD:7087] Lisp_Object の値の妥当性の判定方法について教えてください



藤井です。

Lisp_Object に格納されているアドレスが妥当な値であるかどうかを調べる方
法について教えてください。

まずはこの質問の経緯から説明します。

Meadow を使用していると、突然以下のようなメッセージボックスを表示して終
了します。

    "0x01040cf1" の命令が "0x000000b0" のメモリを参照しました。
    メモリが read になることはできませんでした。

# rev 3977 を最適化あり、デバッグシンボルありで、Cygwin でビルドしてい
# ます。

どこが落ちているのかを以下のように addr2line で確認しました。

    $ addr2line -f -e d:/.../Meadow.exe 0x01040cd1
    mark_object
    /home/fujii/work/Meadow/trunk/src/alloc.c:5247

どうも、mark_object の以下の行で落ちている模様です。

------------------------------------------------------------
	abort ();
#endif /* GC_CHECK_MARKED_OBJECTS */

      if (GC_BUFFERP (obj)) /* <- この行 */
	{
	  if (!VECTOR_MARKED_P (XBUFFER (obj)))
	    {
#ifdef GC_CHECK_MARKED_OBJECTS
------------------------------------------------------------

Meadow 3 では Cygwin でビルドすると LispObject の下位 3 ビットがオブジェ
クトの種別を判定するためのフラグとして用いられるので、LispObject に
int 値をそのまま代入すると、かなりの確率で emacs は整数以外のオブジェク
トだと誤認識します。今回の mark_object で落ちる件もそうだと思っています。

そこで、チェックルーチンを追加して mark_object で LispObject の引数に
不正な値が格納されているかどうかをチェックしたいと考えています。

まず考えたのが、GC_CHECK_MARKED_OBJECTS を定義してオブジェクトを逐一
チェックする方法です。判定精度は高いと思われますが、GC_MARK_STACK が 0
以外であることが利用のための条件となりますので、Meadow では利用できませ
ん。

次に考えたのが、pdump 用のチェックルーチンを利用することです。ですが、
pdump_check_object_validity_Lisp_Vectorlike() では BUFFERP を用いており、
GC_BUFFERP の引数に指定すると落ちる値を BUFFERP に与えても同じく落ちる
ことが予想され、今回の判定には使うのは難しいと考えています。

以上の検討の結果、既存のチェック機構を利用することは無理そうで、チェッ
ク機構を自分で用意するしかなさそうだという結論に至りました。

また、常に GDB 上から起動するようにすればこのようなチェックは必要ないの
ですが、いかんせん発生頻度が非常に低く、発生するまで常に GDB から起動す
るのは非常にしんどいです。ですので、チェックルーチンで異常を見付け、ダ
イアログか何かを表示させた状態でアタッチしてから、GDB を使って原因を究
明したいと考えています。

不正な値を 100% 検知できるまでの精度は必要ないと思いますが、正常値を不
正な値と誤判定するのはなるべく避けたいと思っています。何か良いチェック
方法がありましたら教えて下さい。宜しくお願いします。

--
藤井 正行 / Masayuki FUJII