割り当て解除時のクラッシュは厄介な場合があります。クラッシュが発生することは想定されていません。クラッシュが発生した場合、コードが複雑すぎて簡単に解決策を見つけることができません。
注: InterlockedDecrement
have me の使用は、Windows で作業していることを前提としています。
すべてをログに記録
私自身の解決策は、デバッグ中にクラッシュが発生することはほとんどないため、構築/破壊を大量にログに記録することでした:
this
ポインター値やその他の関連データを含む構造をログに記録します
this
ポインター値やその他の関連データを含む破壊をログに記録します
this
このようにして、が 2 回割り当て解除されたか、まったく割り当てられていないかを確認できます。
...スタックを含むすべて
私の問題はマネージ C++/.NET コードで発生したため、スタックに簡単にアクセスできました。これはありがたいことでした。プレーンな C++ で作業しているように見えるので、スタックを取得するのは面倒かもしれませんが、それでも非常に便利です。
各ログの現在のスタックを出力するには、インターネットからコードを読み込んでみてください。そのためにhttp://www.codeproject.com/KB/threads/StackWalker.aspxで遊んだことを覚えています。
スタックが完全に印刷されるようにするには、デバッグ ビルドにするか、実行可能ファイルに PDB ファイルを含める必要があることに注意してください。
... 複数のクラッシュを含むすべて
Windows を使用していると思います。SEH 例外をキャッチしてみてください。これにより、複数のクラッシュが発生した場合、最初のクラッシュだけではなく、すべてのクラッシュが表示され、ログで「OK」または「CRASHED」とマークできるようになります。マップを使用して割り当て/割り当て解除のアドレスを記憶し、ログを整理して (順番にではなく) 一緒に表示するところまで行きました。
私は家にいるので、正確なコードを提供することはできませんが、Google はあなたの友人ですが、覚えておくべきことは、どこでも__try
/__except
ハンドラーを持つことはできないということです (C++ の巻き戻しと C++ の例外ハンドラーは、 SEH と互換性がありません)、SEH 例外をキャッチするための中間関数を作成する必要があります。
あなたのクラッシュスレッドは関連していますか?
最後になりましたが、「5% の確率でしか発生しません」という現象は、異なるコード パスの実行、または複数のスレッドが同じデータで一緒に実行されていることが原因である可能性があります。
そのInterlockedDecrement
部分は私を悩ませます: あなたのオブジェクトは複数のスレッドに住んでいますか? m_nRefCount は正しく整列されていvolatile
LONG
ますか?
ここでは、正しい位置合わせとLONG
パーツが重要です。
変数が ではない場合LONG
(たとえば、64 ビット Windows ではsize_t
ではない である可能性があります)、関数は間違った方法で動作する可能性があります。LONG
32 バイト境界でアラインされていない変数についても同じことが言えます。#pragma pack()
コードに指示はありますか? あなたのプロジェクト ファイルはデフォルトの位置合わせを変更しますか (Visual Studio で作業していると思います)。
このvolatile
部分についてはInterlockedDecrement
、読み取り/書き込みメモリ バリアを生成するように見えるため、このvolatile
部分は必須ではありません ( http://msdn.microsoft.com/en-us/library/f20w0x5e.aspxを参照)。