2009-10-19 7 views
2

이 문제의 원인은 무엇입니까?std :: map :: iterator가 증가시 프로그램을 충돌 함

여기 스택 추적입니다 :

#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(); 

    } 

편집 :이 다음 문제가 관련이있다, 그래서 나는 완전히 새로운 질문을 열리지 않습니다. 나는 그 것처럼 대답 수용을 떠날 것이다. 나는 단지 무엇인가를 알아야한다. 필자는 두 개의 반복자를 가지고 있는데 하나는 함수 호출 이후에 메인과 하나가된다. 둘 다 같은지도와 관련이 있습니다. 글쎄, 내부의 모든 것이 손상되고 주된 루프가 반복을 멈 춥니 다.

다음은 코드입니다.

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을() :

여기 StartLayout의

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

GetType, SetupChars 또는 Start에서 widgets_을 수정하면 안됩니다. 이것은 당신의 문제 일 가능성이 큽니다.

widgets_을 수정해야하는 경우 그러한 변경이있을 때마다 반복기를 다시 시작해야합니다. 변경 사항을 복제하지 않으려면 루프 외부의 간단한 마커 사전이나 Widget 클래스의 마커 멤버를 사용할 수 있습니다.

+0

'(* w). 초 '가 달라져야한다고 생각하지 않는다 ... – sth

+1

잠깐, 뭐라구? 물론'->'는 표준이며, 어떤 반복자도 과부하 연산자'->'를 제공합니다 - 이것은'Iterator' 특성을위한 요구 사항의 일부입니다! "a-> m; pre : (* a) .m은 잘 정의되어 있으며, 다음과 같이 정의 된 ISO C++ 24.1.1 [lib.input.iterators], 표 72"입력 반복자 요구 사항 "을 참조하십시오.).엠". –

+0

표준 견적 파벨에 감사드립니다. –