自分で調べたよ。
fstream::~fstream()は基本的に例外を投げないようになってる。
fstream::close()は失敗でsetstate(failbit)する(マスクに応じて例外を投げる)。

つまり、閉じるときのエラーを逃さないようにするためには、
fstream::close()を明示的に呼ばなければならない。
デストラクタに任せてしまうと、閉じるときのエラーは検知できない。

明日からはfstream使った後は明示的にcloseしよう。