教祖の瞑想は一応解決

結論: -DDONT_ADD_BYTE_AT_ENDを付けないようにしたら正常にソフトリセットできるようになった。
根本的な原因は、自分がGCのmake時の追加フラグの意味を勘違いしていたのが原因だろう。
しかし、どうしてこんな問題が起こったのか、-DDONT_ADD_BYTE_AT_ENDを使いたい時はどうすればよいのかは不明。


何にせよ、とりあえずは動くようになったという事で、GCいじりは一旦中断。本編の開発に戻る事にする。


以下は、-DDONT_ADD_BYTE_AT_ENDを使いたくなった時に、ここまで調査済みだという事をあとで思い出す為のメモ。




今回の原因は、GCが何故か、確保した領域の一つ後ろ部分をチェックしており、更に不可解な事に、それですぐにはsegvにはならず(プールされてしまっている?)、swiSoftReset()を呼んだ段階でsegvが発生して例外ハンドラが実行され、更に謎な事に例外ハンドラ内で再帰的に例外が発生してしまっている。
……という仮説ぐらいしか思い付かない。

  • エラーになる条件
    • GC_MALLOC()で一つ割り当てただけだと、正常にソフトリセットできる時とエラーになる時がある(何回もソフトリセットしていれば、その内エラーになる)。
    • GC_MALLOC()ではなく、GC_MALLOC_ATOMIC()一回では、常に正常にソフトリセットできていた。
    • GC_MALLOC_ATOMIC()を使っていても、GCが発生した時はソフトリセットはエラーになった。
    • 全くGC_MALLOC()せずにGC_gcollect()を呼んだ時は、どうだったか忘れた。
  • とりあえず、gcc -Eでプリプロセス後のコードを出して洗ってみた。
    • NO_SIGNALSを定義していたので、シグナルマスクを変更している部分は見付からなかった。
    • スタックアンダーフローは別に起こっていなかった。
    • os_dep.c, mach_dep.c に問題の鍵があると思い、かなり調べたが問題部分は見付からなかった。


次に調査を再開する時は、ALL_INTERIOR_POINTERSとDONT_ADD_BYTE_AT_ENDによって変化する辺りを重点的に調査する事。