Seltsamer VC++ Assertion Failure in std::vector



  • Ich bekomme von VC 2008 Expr. eine

    Expression: ("this->HasContainer()",0)
    

    Fehlermeldung.

    Ich habe das zuvor unter Linux und Windows mit dem GCC 4.3.3 einwandfrei übersetzt bekommen.

    Ich stehe hier vor einem Rätzel 😕

    struct CCEWordInfo
          {
              int                    m_Redundancy;
              std::map<char, size_t> m_LetterCount;
              std::vector<char>      m_UniqueLetter;
              std::string            m_Word;
          };
    
        vector<CCEWordInfo*> m_Words;
    
        /* m_Words mit CCEWordInfo* Zeigern füllen */
        ....
    
        vector<CCEWordInfo*>::reverse_iterator rit;
        for(rit = m_Words.rbegin(); rit != m_Words.rend(); ++rit) // <-- ++rit , hier knallts! 
        {
              string word = (*rit)->m_Word;
              iMatch += (m_LastWordUsed[i] == (*rit)->m_Word[i] ? 1 : 0);
    
        }
    

    Mir ist schon klar was die Übersetzung bedeutet, aber warum ?

    Ich hoffe Ihr könnt helfen.. 😞

    EDIT: Den struct hinzugefügt.



  • Ich denke ich habe den Fehler gefunden, das Problem war das löschen des Containers auf dem aktuellen Iterator. Ein Fehler der aber erst mit VC2008 auftaucht, und derzeit vom GCC und WinGW Framework (zurecht wie ich finde) ignoriert wird. Allerdings habe keine 2 Wochen Zeit (und auch keine Lust) mich mit der exakten Funktionsweise der mehrstufigen MSVC Template-Iterator-Prüfung auseinander zu setzen, von d.h. könnte die MS Variante evtl. auch was brauchbares abwerfen.

    So der Code und das warum:

    Der folgende code läuft noch unter VC2005!

    vector<CCEWordInfo*>::reverse_iterator rit;
        for(rit = m_Words.rbegin(); 
    		rit != m_Words.rend(); 
    		++rit)
        {
            size_t iMatch = 0;
            for(size_t i = 0; i < m_LastWordUsed.size(); i++) // <-- hier schreit MS SCL, und erwartet das sich 
                                                              // noch ein gültiger Container hinter dem Iterator 
                                                              // befindet. VC2005 überprüft das nicht - VC2008 schon.
            {
              string word = (*rit)->m_Word;
              iMatch += (m_LastWordUsed[i] == (*rit)->m_Word[i] ? 1 : 0);
            }
    
            if (iMatch != 0)
                m_Words.erase(rit.base()-1);  // <-- das ist jetzt ein Fehler in VC2008!, hier keine remove Aktionen 
                                              // während des Iterierens auf dem aktuellen Iterator gestattet.
        }
    

    MS Forum schrieb:

    In general, avoid removing elements from any standard container while iterating over it. It can be extremely tricky to avoid all possible errors, as you seem to be discovering.

    Daher habe ich den Code folgendermaßen abgeändert:

    vector<CCEWordInfo*>::reverse_iterator rit;
        vector<CCEWordInfo*> vecNewList; // enhält jetzt die zu erhaltenden Elemente
    
        for(rit = m_Words.rbegin(); 
    		rit != m_Words.rend(); 
    		++rit)
        {
            size_t iMatch = 0;
            for(size_t i = 0; i < m_LastWordUsed.size(); i++) // <-- hier jetzt ok
            {
              string word = (*rit)->m_Word;
              iMatch += (m_LastWordUsed[i] == (*rit)->m_Word[i] ? 1 : 0);
            }
    
            if (iMatch == 0)
                vecNewList.push_back(*rit);  // <-- anstatt zu löschen wird umkopiert, nicht toll aber geht
        }
    
        m_Words.clear();
        m_Words.resize(vecNewList.size());
        copy(vecNewList.begin(), vecNewList.end(), m_Words.begin());
        vecNewList.clear();
    
    }
    

    Zum Thema habe ich noch den folgenden Link der mich auf die Spur gebracht hat:
    http://social.msdn.microsoft.com/Forums/en/vclanguage/thread/96318675-b168-4f74-b414-26ef49f46a96

    Und hier eine Liste mit wichtigen Änderungen in VC2008
    http://msdn.microsoft.com/en-us/library/bb531344.aspx

    PS. So toll TMP ist, aber solche Fehler sind oft einfach s**schwer - gerade wegen der TMP - zu finden.

    G-DC!


Anmelden zum Antworten