2009-10-19 4 views
2

Что может быть причиной этого?std :: map :: итератор сбрасывает программу приращения

Вот трассировки стека:

#0 0x0645c0f5 in std::_Rb_tree_increment (__x=0x83ee5b0) 
    at ../../../../libstdc++-v3/src/tree.cc:69 
#1 0x0805409a in std::_Rb_tree_iterator<std::pair<std::string const, Widget*> >::operator++ (
    this=0xbffff144) 
    at /usr/lib/gcc/i586-redhat-linux/4.4.1/../../../../include/c++/4.4.1/bits/stl_tree.h:192 
#2 0x08053d32 in Generic::StartLayout (this=0x8287d68) at Generic.cpp:195 
#3 0x0804f6e1 in LCDControl::ConfigSetup (this=0xbffff26c) at LCDControl.cpp:91 
#4 0x0804ed7c in LCDControl::Start (this=0xbffff26c, argc=1, argv=0xbffff404) at LCDControl.cpp:21 
#5 0x08050964 in main (argc=1, argv=0xbffff404) at Main.cpp:11 

А вот код:

for(std::map<std::string,Widget *>::iterator w = widgets_.begin(); 
     w != widgets_.end(); w++){ 
     if(w->second->GetType() & WIDGET_TYPE_BAR) { 
      w->second->SetupChars(); 
     } 
     w->second->Start(); 

    } 

Edit: Это следующая проблема связана, поэтому я не буду открывать целый новый вопрос. Я оставлю принятие ответа так, как есть. Мне просто нужно кое-что знать. У меня есть два итератора, один основной и один в этом главном после вызова функции. Оба они относятся к одной карте. Ну, внутри внутри все повреждено, а основной цикл останавливает итерацию.

Вот код.

Вот StartLayout:

void Generic::StartLayout() { 
    Error("StartLayout: %s", key.c_str()); 
    for(std::map<std::string,Widget *>::iterator w = widgets_.begin(); 
     w != widgets_.end(); w++){ 
     Error("Starting widget %s", w->first.c_str()); 
     if(w->second->GetType() & WIDGET_TYPE_SPECIAL) { 
      w->second->SetupChars(); 
     } 

     w->second->Start(); 
    } 
} 

А вот SetupChars():

void WidgetGif::SetupChars() { 
    Error("SetupChars <%s> <%s>", name_.c_str(), widget_base_.c_str()); 
    Error("Size of widgets: %d", visitor_->Widgets().size()); 
    std::map<std::string, Widget *> widgets = visitor_->Widgets(); 
    for(std::map<std::string, Widget *>::iterator ii=visitor_->Widgets().begin(); 
     ii != visitor_->Widgets().end(); ii++) { 
     Error("<%s> Widget base %s == %s", ii->first.c_str(), ii->second->GetWidgetBase().c_str(), widget_base_.c_str()); 
     if(ii->second->GetWidgetBase() == widget_base_ && 
      ((WidgetGif *)ii->second)->HasChars()) { 
      Error("Using chars from %s", ii->first.c_str()); 
      for(unsigned int i = 0; i < rows_ * cols_; i++) { 
       if(i >= visitor_->GetLCDText()->CHARS) { 
        Error("1) GIF too large: %s, %d", name_.c_str(), visitor_->GetLCDText()->CHARS); 
        if(update_) delete update_; 
        update_ = new Property(visitor_, section_, "", new Json::Value("-1")); 
        return; 
       } 
        ch_[i] = ((WidgetGif *)widgets[ii->first])->GetChars()[i]; 
      } 
      hasChars_ = true; 
      return; 
     } 
    } 
// It goes on, but I snipped it here. 
} 

И это то, что происходит:

StartLayout: display_qt 
Starting widget widget_gif_american_flag:layout_american_flag:0 
SetupChars <widget_gif_american_flag:layout_american_flag:0> <layout_american_flag> 
Size of widgets: 5 
<widget_gif_american_flag:layout_american_flag:1> Widget base layout_american_flag == layout_american_flag 
<widget_gif_american_flag:layout_american_flag:4> Widget base layout_american_flag == layout_american_flag 
<(n 
(n 
��S> Widget base ГS == layout_american_flag 
^C 

Последнее редактирование: Я понял. Мне просто нужна была копия исходной карты для нового итератора.

+0

Какая функция является фрагментом кода? 'Generic :: StartLayout()'? – sth

+0

@sth: OH извините. Должно было оставить это. Да, ты прав. – Scott

ответ

5

Для этого может быть немало причин. Во-первых, может быть, что GetType или SetupChars или Start сделать что-то, что приведет к изменению вашей карты, что приведет к аннулированию текущего итератора (обратите внимание, что использование operator[] на карте, даже для чтения значения, является технически мутирующей операцией и может вызвать сбой при отладке итератора!). Кроме того, ваша карта может быть повреждена в памяти некоторым кодом, который был выполнен до, например. из-за переполнения буфера, перезаписывающего часть дерева карты.

0

Вы не должны изменять widgets_ любым из своих методов GetType, SetupChars, или Start. Это, скорее всего, ваша проблема.

Если вы должны изменить widgets_, вам потребуется перезапустить итератор при каждом изменении. Чтобы избежать дублирования ваших изменений, вы можете использовать простой словарь маркера вне цикла или элемент маркера класса Widget.

+0

Я не думаю, что '(* w) .second' должен иметь значение ... – sth

+1

Подождите, что? Конечно, '->' является стандартным, любой итератор предлагает перегруженный оператор '->' - это часть требований к признаку 'Iterator'! См. ISO C++ 24.1.1 [lib.input.iterators], Таблица 72 «Требования к входному итератору», определяемые следующим образом: «a-> m; pre: (* a) .m корректно определено. Эквивалентно (* a) .m». –

+0

Спасибо за стандартную цитату Павла. –

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

  • Нет связанных вопросов^_^