7

あまりにも多くの詳細を示すことができないため、この質問が明確になるかどうかはわかりません (私は TPL を使用していて、自分で大量の行を書きました)。でもやってみます。

理解できないセグメンテーション違反が発生しています。デストラクタが次のような構造 (私が設計したわけではありませんが、十分にテストする必要があります) があります。

Data::~Data()
{
  if(A_ != 0) {
    delete A_;
    A_ = 0;
  }

  if(B_ != 0) {
    delete B_;
    B_ = 0;
  }

  if(C_ != 0) {
    delete C_;
    C_ = 0;
  }
} // HERE

私を悩ませているのは、デバッグ中に、「HERE」でマークされた行でセグメンテーション違反が発生していることです。クラス Data は、動的に割り当てられる属性として A_、B_、および C_ のみを持ちます。また、他の非動的複合属性でデストラクタを明示的に呼び出して、破壊中に何か問題が発生したかどうかを確認しようとしましたが、やはりデストラクタの最後でセグメンテーション違反が発生します。その時点でどのようなエラーがセグメンテーション違反を引き起こす可能性がありますか?.

質問が十分に明確であることを願っています。必要に応じて詳細を追加します。

編集:返信ありがとうございます。私はそれがコードの断片であることを知っていますが、ライブラリ全体はもちろん大きすぎます (ちなみに、これは Trilinos から来ていますが、エラーは彼らのせいではないと思います。彼らの構造を処理する際の私の間違いに違いありません。問題をよりコンパクトに保つ​​ための短い名前)。コメントの返信で誰かが尋ねたいくつかの発言:

  • 削除の前のチェックと生のポインターについて: 私が言ったように、それは私の選択ではありません。何か問題が発生し、A_、B_、または C_ がデータ構造の他の所有者によって既に削除されている場合の二重の保護だと思います。raw-pointers と shared_ptr またはその他のセーフ/スマート ポインターの選択は、おそらく、このクラスが直接使用されることはほとんどなく、Data へのポインターを持つクラス Map のオブジェクトによってのみ使用されるという事実によるものです。このクラス Map は同じライブラリに実装されているため、何をどのように処理しているかを知っていたので、おそらく未加工のポインターを選択しました。
  • はい、データ構造は同じオブジェクトのすべてのコピーで共有されます。特に、Data オブジェクトへのポインターを含む Map クラスがあります。お互いのコピーであるすべてのマップは、同じデータを共有します。参照カウンターは、データへのポインターを保持している Map の数を追跡します。破棄される最後のマップは、データを削除します。
  • データ構造の参照カウンターが正しく動作することを確認しました。
  • このクラスのデストラクタを呼び出していません。Data へのポインタを属性として持つクラス Map のオブジェクトのデストラクタによって自動的に呼び出されます。
  • データは BaseData から継承されます。この (仮想) デストラクタはクラスを定義する単なるインターフェイスであるため、何もしません。
  • 問題を再現するコードを投稿するのは難しいです。多くの理由で。エラーは2つ以上のプロセスでのみ表示されます(これはmpiプログラムです)。プロセスには空のリストがあり、いくつかの要素にアクセスしようとしていると思います。
  • エラーの詳細について。デバッグ中のエラーのバックトレースの最後の項目をここに示します (形式が悪くて申し訳ありませんが、うまく表現する方法がわかりません)。

    1. ../nptl/sysdeps/unix/sysv/linux/raise.c:64 でのレイズ (sig=) の 0x00007ffff432fba5

    2. 0x00007ffff43336b0 in abort () at abort.c:92

    3. ../sysdeps/unix/sysv/linux/libc_fatal.c:189 の __libc_message (do_abort=, fmt=) の 0x00007ffff436965b

    4. malloc_printerr の 0x00007ffff43736d6 (action=3、str=0x7ffff4447780 "free(): 破損した未ソートのチャンク"、ptr=)、malloc.c:6283

    5. malloc.c:3738 の __libc_free (mem=) の 0x00007ffff4379ea3

    6. /home/bartgol/LifeV/trilinos/trilinos-10.6.4-src/packages/epetra/src/Epetra_BlockMapData.cpp:110 の Epetra_BlockMapData::~Epetra_BlockMapData (this=0x1461690, __in_chrg=) の 0x0000000000c21f71

すべての属性が既に削除されている場合でも、デストラクタの最後にどのようなエラーが表示されるのでしょうか? 再度、感謝します!

4

3 に答える 3

5

関数の終了時にsegfaultを引き起こす問題の 1 つは、ヒープまたはスタックの破損です。

プログラムの他の部分が問題を引き起こしている可能性があります。double -destructionバッファ オーバーランなどによって、メモリが破損する可能性があります。

多くの場合、プログラムのデバッグ ビルドには、スタックが損なわれていないことを確認するための関数終了時のチェックが含まれます。そうでない場合は、結果が表示されます。

于 2012-07-31T02:04:58.120 に答える
2

クラスデストラクタの明示的な本体が完了すると、いくつかの暗黙的なアクションの実行に進みます。基本クラスとメンバーのデストラクタを呼び出し(基本クラスとメンバーに重要なデストラクタがある場合)、必要に応じて、生のメモリの割り当て解除を呼び出します。関数operator delete(はい、通常の実装operator deleteでは、実際にはデストラクタの内部から呼び出されます)。これらの2つの暗黙のプロセスの1つが、明らかにあなたのケースでクラッシュを引き起こしました。より多くの情報なしで正確に言う方法はありません。

PSスタイル的にコードはひどいです。なぜ彼らは行う前にnullをチェックしているのdeleteですか?デストラクタで削除されたポインタを無効にすることのポイントは何ですか?

于 2012-07-31T04:56:15.943 に答える
0

あなたが示す希少なコードからはわかりにくいです。クラス メンバーの 1 つまたは基本クラスが独自のデストラクタで使用するリソースを既に解放している可能性があります。

于 2012-07-30T18:05:38.330 に答える