3

ここ数日、奇妙なケースをデバッグしており、バグをある程度分離しましたが、まだ意味がありません。おそらく、ここにいる誰かが何が起こっているのかについての手がかりを教えてくれるでしょう。

問題は、コードの一部で発生するアクセス違反です。

基本的に、次のようなものがあります。

void aclass::somefunc() {
  try {
    erroneous_member_function(*someptr);
  } 
  catch (AnException) {
  }
}

void aclass::erroneous_member_function(const SomeObject& ref) {
  // { //<--scope here error goes away
  LargeObject obj = Singleton()->Object.someLargeObj; //<-remove this error goes away

  //DummyDestruct dummy1//<-- this is not destroyed before the unreachable

  throw AnException();

  // } //<--end scope here error goes away 

  UnreachableClass unreachable; //<- remove this, and the error goes away

  DummyDestruct dummy2; //<- destructor of this object is called! 
}

デバッガーでは実際に UnreachableClass を破棄しているように見えますが、DummyDestruct オブジェクトを挿入すると、奇妙なデストラクタが呼び出される前に破棄されません。したがって、LargeObject の破壊が失敗しているようには見えません。

これはすべて本番コードの途中にあり、小さな例に分離するのは非常に困難です。

私の質問は、これを引き起こしている原因と何が起こっているのかについて手がかりを持っている人はいますか? 非常にフル機能のデバッガー (Embarcadero RAD studio) を使用できますが、どうすればよいかわかりません。

続行する方法について誰かアドバイスをもらえますか?

アップデート:

DummyDestruct オブジェクトを throw 句の下に配置し、デストラクタにブレークポイントを配置しました。このオブジェクトのデストラクタが入力されます (そして、このコードには私たちだけが含まれています)。

4

5 に答える 5

1

あなたが提供した情報で、すべてがあなたが述べたとおりであれば、可能な唯一の答えはコンパイラ/オプティマイザのバグです。コメントを付けて追加のスコープを追加するだけです(これは、すべてがあなたが述べたとおりである場合です)。

于 2010-02-24T13:26:05.520 に答える
1

このようなことは、初期化されていないポインターを介した書き込み、範囲外の配列アクセスなどが原因で発生することがあります。エラーが発生するポイントは、エラーが発生する場所からかなり離れている可能性があります。ただし、説明した症状に基づいて、この機能にローカライズされているようです。のコピー コンストラクターのLargeObject動作がおかしい可能性はありますか? ref は使用されていますか? 有効somePtrな を指していない可能性がありますSomeObjectSingleton()有効なオブジェクトへのポインタを返していますか? 特にアグレッシブな最適化がオンになっている場合は、コンパイラ エラーも発生する可能性があります。最適化なしでバグを再現しようとします。

于 2010-02-24T13:56:36.663 に答える
1

テレパシー デバッグ スキルを練習する時間です。

私の推測では、アプリケーションにスタック破損のバグがあると思われます。これにより、コール スタックにジャンクが書き込まれる可能性があります。これは、デバッガーがブレーク時に関数を誤って報告していることを意味し、実際にはデストラクタにはありません。それか、デバッガーの情報を誤って解釈していて、オブジェクトが実際に正しく破棄されているかのどちらかですが、その理由はわかりません!

スタックが破損している場合、根本的な原因を突き止めるのに非常に苦労することになります。これが、プログラム全体に大量の診断 (アサートなど) を実装することが重要である理由です。そうすれば、奇妙な副作用にとらわれるのではなく、スタックの破損が発生したときにそれをキャッチできます。

于 2010-02-24T13:57:28.690 に答える
0

あなたが文字列について言及したので、ここにもう一つの野蛮な推測があります。(STL)文字列のコピーが遅延して行われる実装を少なくとも1つ知っています(つまり、変更が行われるまで文字列の内容の実際のコピーは行われません。「コピー」は、ターゲットの文字列オブジェクトを使用するだけで行われます。ソースと同じバッファを指します)。その特定の実装(GNU)には、過度のコピーによって参照カウンター(おそらくコピー後に同じ実際の文字列メモリを使用しているオブジェクトの数)が0にロールオーバーし、あらゆる種類のいたずらが発生するというバグがあります。私自身はこのバグに遭遇したことはありませんが、発生した人からこのバグについて知らされました。(これは、refカウンターが32ビットの数値であり、ロールオーバーする可能性が非常に低いためです。控えめに言っても、

于 2010-02-24T14:11:32.857 に答える
0

これは本当のロングショットかもしれませんが、とにかくそこに出すつもりです...

あなたは borland を使用していると言いますが、どのバージョンですか? そして、文字列にエラーが表示されると言います-STL?プロジェクトに winsock2 を含めますか?

私が尋ねる理由は、borland 6 (2002) と winsock を使用しているときに問題が発生したためです。ヘッダーが構造パッキングを台無しにしているように見え、異なる翻訳単位が std::string のメモリ レイアウトについて異なる考えを持っていたことを意味します。どのヘッダーが翻訳単位に含まれていたのか、予想通り悲惨な結果をもたらしました。

于 2010-02-24T14:02:05.233 に答える