2009-10-19 11 views
2

Qu'est-ce qui pourrait causer cela?std :: map :: iterator plante le programme par incrément

est ici la trace de la pile:

#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 

Et voici le code:

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: Ce problème suivant est lié, je ne vais pas ouvrir une nouvelle question tout. Je laisserai la réponse acceptée comme elle est. J'ai juste besoin de savoir quelque chose. J'ai deux itérateurs, un principal et un principal après un appel de fonction. Ils se rapportent tous les deux à la même carte. Eh bien, celui qui est à l'intérieur est corrompu, et la boucle du principal arrête d'itérer.

Voici le code.

Voilà 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(); 
    } 
} 

Et voici 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. 
} 

Et voici ce qui se passe:

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 

Dernière modification: Je compris. J'avais juste besoin d'une copie de la carte originale pour le nouvel itérateur.

+0

De quelle fonction provient l'extrait de code? 'Generic :: StartLayout()'? – sth

+0

@sth: OH désolé. Shoulda l'a laissé. Oui tu as raison. – Scott

Répondre

5

Il pourrait y avoir plusieurs raisons à cela. Pour un, il se peut que GetType ou SetupChars ou Start fasse quelque chose qui change votre carte - ce qui invaliderait l'itérateur actuel (notez que l'utilisation de operator[] sur la carte, même juste pour lire la valeur, est techniquement une opération de mutation, et peut provoquer un crash avec le débogage d'itérateur activé!). Alternativement, votre carte pourrait être corrompue en mémoire par un code qui a été exécuté avant, par ex. en raison d'une saturation de la mémoire tampon de l'arborescence de la carte.

0

Vous ne devez pas modifier widgets_ dans aucune de vos méthodes GetType, SetupChars ou Start. C'est probablement votre problème.

Si vous devez modifier widgets_, vous devrez redémarrer l'itérateur chaque fois qu'une telle modification est apportée. Pour éviter de dupliquer vos modifications, vous pouvez utiliser un simple dictionnaire de marqueurs en dehors de la boucle ou un marqueur de la classe Widget.

+0

Je ne pense pas que '(* w) .second' devrait faire une différence ... – sth

+1

Attends, quoi? Bien sûr '->' est standard, tout itérateur offre un opérateur surchargé '->' - cela fait partie des exigences pour le trait 'Iterator'! Voir ISO C++ 24.1.1 [lib.input.iterators], Tableau 72 "Exigences de l'itérateur d'entrée", défini comme suit: "a-> m; pre: (* a) .m est bien défini.) .m ". –

+0

Merci pour les normes devis Pavel. –