2010-05-19 5 views
1

(Примечание для будущих читателей: Ошибка, что не удивительно, в моем коде, а не STD :: _ Rb_tree_rebalance_for_erase())вина Сегментация в станд функции станд :: _ Rb_tree_rebalance_for_erase()

Я несколько новых для программирования и я не уверен, как бороться с ошибкой сегментации, которая, как представляется, поступает из функции std. Надеюсь, я делаю что-то глупое (т. Е. Неправильно использую контейнер), потому что я понятия не имею, как это исправить.

Точная ошибка

Программа получила сигнал EXC_BAD_ACCESS, не удалось получить доступ к памяти.
Причина: KERN_INVALID_ADDRESS по адресу: 0x000000000000000c
0x00007fff8062b144 в станд :: _ Rb_tree_rebalance_for_erase()
(GDB) трассировку
# 0 0x00007fff8062b144 в станд :: _ Rb_tree_rebalance_for_erase()
# 1 0x000000010000e593 в моделировании :: runEpidSim (это = 0x7fff5fbfcb20) в stl_tree.h: 1263
# 2 0x0000000100016078 в основной() в main.cpp: 43

функция, которая выходит успешно как раз перед обновит ошибки сегментации содержимое двух контейнеров. Один из них - boost::unordered_multimap под названием carriage; он содержит один или несколько объектов struct Infection. Другой контейнер имеет тип 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 << линия появляется непосредственно перед вине SEG.

Моя идея до сих пор заключается в том, что после этой функции выполняется попытка перебалансировки на ce, но я не уверен, что перебалансировка будет неудачной.


Update

Я подтвердил вину сегм уходит (хотя программа тут же падает и по другим причинам), когда я удаляю ce.erase(epqItr);. Я могу успешно удалить события в другом месте в коде; код, который я использую для стирания элементов в ce, равен идентичным тому, что здесь.

обратной трассировке без оптимизации (спасибо, БДК) показывает намного больше информации:

Программа получила сигнал EXC_BAD_ACCESS, не удалось получить доступ к памяти.
Причина: KERN_INVALID_ADDRESS по адресу: 0x000000000000000c
0x00007fff8062b144 в станд :: _ Rb_tree_rebalance_for_erase()
(GDB) трассировку
# 0 0x00007fff8062b144 в станд :: _ Rb_tree_rebalance_for_erase()
# 1 0x00000001000053d2 в станд :: _ Rb_tree, станд: : less,> std :: allocator> :: erase (this = 0x7fff5fbfdfe8, __position = {_ M_node = 0x10107cb50}) at> stl_tree.h: 1263
# 2 0x0000000100005417 в std :: multiset, std :: allocator> :: erase (this = 0x7fff5fbfdfe8, __position = {_ M_node = 0x10107cb50}) в stl_multiset.ч: 346 # 3 0x000000010000ba71 в моделировании :: runEpidSim (это = 0x7fff5fbfcb40) при Simulation.cpp: 426
# 4 0x000000010001fb31 в главной() в main.cpp: 43

Если Xcode не читает номера строк неправильно, единственный stl_tree.h на моем жестком диске пуст в строке 1263.

Несколько человек попросили увидеть функцию, которая вызывает восстановление. Это немного сложнее:

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. Перейти ниже для неловкого решения.

+0

Что находится на stl_tree.h: 1263? –

+0

Единственный stl_tree.h, который отображается на моем жестком диске (также единственный файл, содержащий «_Rb_tree_rebalance_for_erase» на моем HD), * * * в строке 1263 (?!). Я использую gcc 4.2.1 (Apple build 5646) на i686-apple-darwin10. Функция rebalance_for_erase определена в строках 299-429. – Sarah

+1

Если вы поместили cout в вызывающий код сразу после вызова Host :: recover, распечатывается ли это? Кроме того, попробуйте выполнить компиляцию со всеми оптимизациями и отключением вложения, и вы можете получить более полезную трассировку стека – bdk

ответ

3

Возможно, вы держите на итераторе в ce по вызову для восстановления. Если восстановление удалит этот элемент, итератор будет признан недействительным, и любое использование в будущем (например, попытка удалить его) может привести к ошибке seg.

Это поможет, если мы увидим больше контекста того, как ce используется до и после вызова для восстановления.

+0

Вы правы! (Мне нужно посмотреть, как и когда происходит ребалансировка дерева). – Sarah

0

Возможно, звонок в assert не скомпилирован с вашей конфигурацией. Утверждения в производственном коде обычно являются плохими идеями [TM].

Вы также можете превысить границы immune.

Try:

if (epqItr != ce.end()) 
    { 
     ce.erase(epqItr); 
     if (z is within immune's bounds) 
     { 
      ++immune[z]; 
     } 
    } 
1

Проблема заключалась в том, что на линии 426 Simulation.cpp, я попытался удалить событие в EventPQ currentEvents (А.К.А. ce) контейнера, что моя recover() функция только удален. Итератор, очевидно, был признан недействительным. Тупой.

Уроки:

  • отладки на коде, который не был оптимизирован
  • Обратите пристальное внимание на то, что Нестандартный связанные кадры подразумевают

И на будущее: Трассировка памяти in valgrind

Я все еще тупой, почему отладчик сослал меня на явно пустую строку в stl_tree.h.

У меня есть огромная оценка здесь для людей, которые помогли мне справиться с этим. Я собираюсь пересмотреть свой вопрос, чтобы он был более кратким для будущих читателей.

+1

Это общее правило, которое следует соблюдать, когда вы сталкиваетесь с сбоем. Посмотрите на стоп-лоток сверху вниз, пока не нажмете свой собственный код и не начнете смотреть туда. Как правило, вы обнаружите, что ошибка вызвана где-то в этой стеке в вашем собственном коде, а не в библиотеке. Когда это не так, вы, как правило, обнаружите, что вы ударили UB полчаса назад и сейчас просто сталкиваетесь с тем, что вызвало. Я на самом деле никогда не сталкивался с ошибкой библиотеки. Запустите LOT ошибок компилятора, но я не могу придумать какой-либо ошибки библиотеки. –

Смежные вопросы