2

(将来の読者への注意:当然のことながら、エラーは私のコードにあり、 std::_Rb_tree_rebalance_for_erase () ではありません)

私はプログラミングに少し慣れていないため、std 関数から発生しているように見えるセグメンテーション違反に対処する方法がわかりません。修正方法がわからないので、何かばかげたこと (つまり、コンテナーの誤用) をしているといいのですが。

正確な誤差は

プログラムは信号 EXC_BAD_ACCESS を受信しました。メモリにアクセスできませんでした。
Reason: KERN_INVALID_ADDRESS at address: 0x000000000000000c
0x00007fff8062b144 in std::_Rb_tree_rebalance_for_erase ()
(gdb) backtrace
#0 0x00007fff8062b144 in std::_Rb_tree_rebalance_for_erase ()
#1 0x000000010000e593 in Simulation::runEpidSim (this=0x7fff5fbfcb20) at stl_tree.h:1263
#2 main.cpp:43 のメイン () の 0x0000000100016078

セグメンテーション違反の直前に正常に終了する関数は、2 つのコンテナーの内容を更新します。1 つはboost::unordered_multimap呼び出されcarriageた ; 1 つ以上のstruct Infectionオブジェクトが含まれています。もう 1 つのコンテナは、std::multiset< Event, std::less< Event > > EventPQと呼ばれるタイプceです。

void Host::recover( int s, double recoverTime, EventPQ & ce ) {

  // Clearing all serotypes in carriage
  // and their associated recovery events in ce
  // and then updating susceptibility to each serotype
  double oldRecTime;
  int z;
  for ( InfectionMap::iterator itr = carriage.begin(); itr != carriage.end(); itr++ ) {
    z = itr->first;
    oldRecTime = (itr->second).recT;
    EventPQ::iterator epqItr = ce.find( Event(oldRecTime) );
    assert( epqItr != ce.end() );
    ce.erase( epqItr );
    immune[ z ]++; 
  }
  carriage.clear();
  calcSusc(); // a function that edits an array 
  cout << "Done with sync_recovery event." << endl;
}

最後のcout << 行は、セグ フォールトの直前に表示されます。

ceこれまでの私の考えでは、この関数の直後にリバランスが試みられていますが、リバランスが失敗する理由はわかりません。


アップデート

を削除すると、セグフォルトがなくなることを確認しました (ただし、プログラムは他の理由ですぐにクラッシュします) ce.erase( epqItr );。コード内の別の場所でイベントを正常に削除できました。アイテムを消去するためにそこで使用するコードは、ここにあるものce同じです。

最適化なしのバックトレース(ありがとう、bdk) は、より多くの情報を明らかにします:

プログラムは信号 EXC_BAD_ACCESS を受信しました。メモリにアクセスできませんでした。
Reason: KERN_INVALID_ADDRESS at address: 0x000000000000000c
0x00007fff8062b144 in std::_Rb_tree_rebalance_for_erase ()
(gdb) backtrace
#0 0x00007fff8062b144 in std::_Rb_tree_rebalance_for_erase ()
#1 0x00000001000053d2 in std::_Rb_tree, std::less, > std::allocator >: :erase (this=0x7fff5fbfdfe8, __position={_M_node = 0x10107cb50}) at > stl_tree.h:1263
#2 0x0000000100005417 in std::multiset, std::allocator >::erase (this=0x7fff5fbfdfe8, __position={_M_node10 = 0x7fff5fbfdfe8, __position={_M_node10 = 0x7ff51 }) stl_multiset.h:346 で #3 Simulation::runEpidSim で 0x000000010000ba71 (this=0x7fff5fbfcb40) Simulation.cpp:426 で
#4 main () で main.cpp:43 で 0x000000010001fb31

Xcode が行番号を間違って読み取っていない限り、ハード ドライブの stl_tree.h だけが行 1263 で空白になっています。

数人が、recover を呼び出す関数を確認するよう求めました。少し複雑です:

struct updateRecovery{
updateRecovery( int s, double t, EventPQ & ce ) : s_(s), t_(t), ce_(ce) {}
  void operator() (boost::shared_ptr<Host> ptr ) {
   ptr->recover( s_, t_, ce_ );
  }
private:
  int s_;
  double t_;
  EventPQ & ce_;
};

// allHosts is a boost::multiindex container of boost::shared_ptr< Host > 
// currentEvents is the EventPQ container
// it is an iterator to a specific member of allHosts
allHosts.modify( it, updateRecovery( s, t, currentEvents ) );
cout << "done with recovery" << endl;

最後のcoutプリント。この特定のバージョンの回復機能がなくても、コードは以前は機能していました。

Noah Roberts は、問題が Simulation.cpp の 426 行目にあることを正しく指摘しました。恥ずかしい解決策については、以下にジャンプしてください。

4

3 に答える 3

3

ceおそらく、回復するために呼び出し全体でイテレータを保持しています。リカバリによってそのアイテムが削除された場合、イテレータは無効になり、将来の使用(たとえば、アイテムの消去の試み)により、セグメンテーション違反が発生する可能性があります。

ceリカバリの呼び出しの前後でどのように使用されるかについて、より多くのコンテキストを確認できれば役立ちます。

于 2010-05-19T21:33:20.890 に答える
1

問題は、Simulation.cpp の 426 行目で、関数が削除したばかりのEventPQ currentEvents(別名ce) コンテナー内のイベントを削除しようとしたことです。recover()イテレータは明らかに無効化されていました。バカ。

教訓:

  • 最適化されていないコードのデバッグ
  • 非標準関連のフレームが何を意味するかに細心の注意を払う

そして将来のために: valgrind でメモリをトレースする

なぜデバッガーが stl_tree.h の明らかに空白の行を参照したのか、私はまだ困惑しています。

ここで、私がこれを乗り越えるのを手伝ってくれた人々に心から感謝しています。将来の読者にとってより簡潔になるように、質問を修正します。

于 2010-05-19T21:37:20.117 に答える
0

おそらく、への呼び出しassertは設定でコンパイルされていません。本番コードでのアサーションは通常、悪いアイデア[TM]です。

immuneまた、の境界を超えている可能性があります。

試す:

    if (epqItr != ce.end()) 
    {
        ce.erase(epqItr);
        if (z is within immune's bounds)
        {
            ++immune[z]; 
        }
    }
于 2010-05-19T21:36:34.050 に答える