これはとても腹立たしいです!>_<
巨大で複雑な Haskell ライブラリを作成しました。私は小さなテスト プログラムを書きましたが、これまでのところ、クラッシュし続ける理由を突き止めるために約 8 時間費やしました。GHC は「奇妙なクロージャ タイプ」について不満を言うことがあります。時々、セグメンテーション違反が発生します。明らかに問題はメモリの破損です。
ライブラリ自体は 100% 純粋な Haskell です。ただし、テスト プログラムは、配列に関連するいくつかの安全でない GHC プリミティブを使用します。これが明らかに問題の原因です。実際、その行をコメントアウトするwriteArray#
と、プログラムはクラッシュしなくなります。しかし、これは私の麺を完全に揚げています...私が知る限り、私が使用したすべての配列境界は完全に有効です。プログラムはそれらをすべて出力します。それらはすべて正で、配列サイズよりも小さいです。
最初のプログラムと同じことを行う 2 番目のプログラムを作成しましたが、巨大で複雑なライブラリは必要ありません。私は試してみましたが、まったくクラッシュさせることはできません。私が何をしてもクラッシュするようには見えませんが、実際の配列とほぼ同じことを行います。
他にトラブルシューティングのヒントはありますか? メモリが破損している正確な瞬間を追跡する方法はありますか? (システムが破損に気付いた瞬間ではありません。)
アップデート:
問題は何をしますか?
基本的には、ピクセル バッファーを表す配列を作成します。すべてのピクセルを反復処理し、対応する値を書き込む 1 つのスレッドを生成します。そして、配列を読み取る 2 番目のスレッドを生成し、かなり複雑なプロトコルを使用してピクセルをネットワーク ソケットに書き込みます。(したがって、私がテストしようとしている大きなライブラリ。)
ライター スレッドを生成しないと、クラッシュはなくなります。ライター スレッドで呼び出しをコメント アウトするwriteArray'
と、クラッシュはなくなります。各ピクセルを書き込む前に、書き込みスレッドはピクセル座標と配列インデックスを出力します。印刷されるものはすべて完璧に見えます。それでも... クラッシュが止まりません。
GHCの配列プリミティブがスレッドセーフか何かではないのだろうか。(何らかの違いが生じた場合に備えて、リーダー スレッドのように見える配列のコピーは安全に凍結されていませんが、ライター スレッドはそれを並行して変更し続けます。)
ただし、ネットワーク経由でトラフィックを送信せずに、まったく同じことを行うプログラムを作成しました。このプログラムは細部まで完璧に機能します。機能しないのは、本当に複雑なプログラムだけです。それはどれほど迷惑ですか?
これは動作します: http://hpaste.org/70987
これはそうではありません: http://hpaste.org/70988