(遅すぎる、あるいはメモリを食いすぎるHaskellプログラムについては、第6章. より早く、より高速で、より小さく、より慎ましくあるための助言を見てほしい)
(つまり、「セグメンテーション違反」や「core dumped」)
プログラムで外部呼び出しを行っておらず、安全でないと分かっている関数(unsafePerformIO
など)も使っていないなら、一つの例外をのぞいて、これは常にGHCシステムのバグである。例外とは、プログラムが複数のモジュールから成り立っているとき、それぞれのモジュールは、そのモジュールが依存しているモジュールが全てコンパイルされた後でコンパイルされなければならない(.hi-boot
を使う場合を除く。この場合それらはモジュールのソースと正しく対応していなければならない)、という条件に反した場合である。
例えば、インポートされる値の型について、インタフェースファイルに誤った情報がある場合、インポート元モジュールの生成コードが壊れることになる。これは、インタフェース中のプラグマにも適用される。プラグマに誤った情報(例えば値の項数について)がある場合、壊れたコードが得られる。さらに、型が変わらなくても項数が変わることがあり得る。
簡単に言うと、モジュールをコンパイルした後にそのインタフェースが変わったら、そのインタフェースをインポートするモジュールは全て再コンパイルしなければならない。
インタフェースが変わったときに知らせてくれる便利なオプションとして-hi-diffs
がある。これは、変更のあったインタフェースファイルにdiffを施すものである。
makeを使っているなら、依存性情報を自動的に生成して、全てのモジュールが、インポート先インタフェースに対して、古くならないようにすることができる。4.7.11. 依存関係を生成するを参照してほしい。
「バグ報告の前の最後のコンパイル」をすることになったら、コンパイルオプションに-dcore-lint
を追加する(より詳しい検査ができる)ことを推奨する。
つまり、core dumpするとしてバグを報告する前に、次のようなことをするべきだろう。
% rm *.o # オブジェクトファイルを片付ける % make my_prog # プログラムを再makeする。変更点をはっきりさせるには-hi-diffsを使う。 # 上述のように、より偏執的に-dcore-lintを使うこともできる。 % ./my_prog ... # もう一回...
もちろん、プログラム中に外部関数の呼び出しがあるなら、話は全く別である。ヒープを破壊したり、スタックを破壊したり、なんでもできるからである。
これは間違いなくGHCのバグが原因である。報告してほしい。(1.3. GHCのバグを報告するを見よ)
Int
、Float
、Double
の四則演算は検査されない。オーバーフロー、アンダーフロー、精度の損失は、黙って見過ごされるか、OSによって例外として報告される(どちらかはシステムによる)。零による除算の結果、受け取られない例外が発生するかもしれない。(もしそうなったら報告してほしい)