または私は如何にして残当したか

こちらの放置がひどく、情けないことです。研究室でやってることは基本的にイミフというか、文章に起こしにくいというか…。未発表の研究なるものを言ってしまうのもまずいっぽいし…。


研究室配属の件ですが、ilabで絶賛希望状況調査中です。私の予想に反して(爆笑)第1希望が5/8人もいるようなのですが…。私は煽り(爆笑)の可能性を否定できないでいるのですが…。
※直前期に更新が止まり、自分の希望変更だけできるようになる


アラインメントミス*1するという謎の挙動を調査するためごちゃごちゃしていたところ、一度VMの部分だけを普通にPCのLinux GCCで(-Dprintk=printfなどして半ば無理やり)コンパイルして調査しようと思ったのです。

gcc -O0 -g ...

-gでデバッグ用情報をつけ、-O0(オーゼロ)で最適化を切ります。が、すると…

Segmentation Fault

そして…-O2(最適化オン)だと普通に動く。……これはまずい。非常に良くない。騒いだりしてもなにも好転しないことは知っているので気分だけは落ちついているが…。
gdbで見ると(VMの)スタックからpopしたunionのポインタがぶっ壊れている、スタックが正しく戻せていない様子。
仕方ないので-gをつけて-O0と-O2の部分だけ変えたバイナリを生成する.PHONYターゲットをMakefileにやっつけで作成。2つの端末からgdbで同時実行…。
そしてついに変数vmStackPtrの値が最終的に1ずれていることを突きとめた(最適化かけると変数がメモリから削除されてたり、メモリへの反映が遅くなったりしてgdbで追いかけるのがつらい…)。そしてvmStackPtrの宣言にvolatileをつけ(ヘッダのextern宣言も合わせないといけなくて面倒だった)てvmStackPtrに対する最適化を止めてやると…。-O2でも死んだ。
vmStackPtrが同じところと違うところで挟みこんで数えると20行程度。

gccにバグがあるか、このコードが実は未定義動作のアレかの二択だが、ほぼ間違いなく後者だろう…。
twitterより

vmStackPtrを使っており、かつ未定義の動作を引き起こすような部分をガン見して探す。幸いターゲット量は少ない。

vmStackPtr -= vmStack[--vmStackPtr].intValue;

アッー!

vmStackPtr -= vmStack[vmStackPtr - 1].intValue;
vmStackPtr--;

どうやらこういうことがしたかったらしい。
そう、同じコンパイラ(gcc)でも最適化レベルによって挙動が変わることがあるのが未定義動作の怖いところ…。言語がクソともいえるし、何がどうとでも言える。
※かいつまんで書いてますが、5時間くらいかかってます。


…これって研究室の宣伝になるの?

*1:例えば4の倍数でないアドレスに4バイトロード・ストア命令を実行するとCPU例外が発生する。実はx86系では遅くなるだけでなんとかしてくれてしまうからなじみがないかもしれないが、そういう対応の方がまれ。