2

これを削除しようとすると、セグメンテーション違反が発生します。

これを削除することについてあなたがどう思うかはわかりますが、私の前任者が残したものです。私が取るべきいくつかの予防措置を認識しており、それらは検証され、対処されています。

どのような状況でこのクラッシュが発生するかはわかりませんが、たまにしかありません。約 95% の場合、コードは完全に正常に実行されますが、何らかの理由で破損しているように見えてクラッシュすることがあります。

クラスのデストラクタは何もしません。

何かが私のヒープを別の場所で破損していて、this ポインターが何らかの形で台無しになっていると想定する必要がありますか?

編集:要求どおり、クラッシュコード:

long CImageBuffer::Release()
{
  long nRefCount = InterlockedDecrement(&m_nRefCount);
  if(nRefCount == 0)
  {
    delete this;
  }
  return nRefCount;
}

オブジェクトは new で作成されました。どの種類の配列にもありません。

4

3 に答える 3

1

最も明白な答えは:これを削除しないでください。

それを主張する場合は、バグを見つける一般的な方法を使用してください:
1. valgrind(または同様のツール)を使用してメモリアクセスの問題を見つけます
2.単体テスト
を作成します3.デバッガーを使用します(画面を見つめるloooongの準備-方法によって異なりますあなたのプロジェクトは大きいです)

于 2011-09-16T19:17:18.153 に答える
1

newと が一致していないようですdeletedelete this;を使用して割り当てられたオブジェクトでのみ使用できることに注意してくださいnew(オーバーライドされたoperator new、または C++ ランタイムの複数のコピーの場合、現在のスコープで見つかった特定newdeleteもの)

于 2011-09-16T19:21:08.453 に答える
0

割り当て解除時のクラッシュは厄介な場合があります。クラッシュが発生することは想定されていません。クラッシュが発生した場合、コードが複雑すぎて簡単に解決策を見つけることができません。

注: InterlockedDecrementhave me の使用は、Windows で作業していることを前提としています。

すべてをログに記録

私自身の解決策は、デバッグ中にクラッシュが発生することはほとんどないため、構築/破壊を大量にログに記録することでした:

  1. thisポインター値やその他の関連データを含む構造をログに記録します
  2. 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を参照)。

于 2011-09-18T10:05:50.433 に答える