[GELÖST] Iterator zu Integer?



  • CStoll schrieb:

    314159265358979 schrieb:

    Wobei Sky's Lösun bei std::vector besser wäre. O(1).

    std::distance() läuft auf Random Access Iteratoren auch in O(1).

    Stimmt, TMP ftw 🤡



  • Beides funktioniert in meinem Fall (danke also auch an Skym0sh0), aber wenn ich button_.begin() mehrmals abrufen will, crasht das Programm auf die ein oder andere Weise (Speicherfehler, Einfrieren, ...)

    Weiß jemand Abhilfe?

    EDIT:

    corrupted double-linked list

    und Einfrieren sind die häufigsten Fälle.

    Ich Ent-[GELÖST]-e mal. 😞

    EDIT2:

    Fehler treten scheinbar dann auf, wenn ich eine Integer-Klassenvariable auf diese Art und Weise erstelle und dann in der Laufzeit button.begin() abrufe.



  • Guck mal in die Doku Deines Compilers / Standardbibliotheks-Providers nach, was der/die alles so an Debug-Möglichkeiten hergibt. Sofern man nicht auf unterster Abstraktionsebene programmiert (roher Speicher, Zeigerfrickeleien), kann man so sehr viele Fehler abfangen. Ich meine jetzt nicht nur einen Debug-Modus des Compilers, sondern auch einen Debug-Modus der Standardbibliothek mit "checked iterators" etc.

    Und sonst musst Du Dein Programm selbst stark vereinfachen und versuchen den Fehler zu isolieren.

    Bist Du Dir ganz sicher, dass Du nicht vielleicht die Underschiede zwischen C++ und einer dir besser vertrauten Sprache unterschätzt? Das geht nämlich vielen Anfängern so...

    Für weitere Tipps fehlt da jetzt der Kontext. Im Code sehe ich zB nirgends eine Liste.



  • krümelkacker schrieb:

    Bist Du Dir ganz sicher, dass Du nicht vielleicht die Underschiede zwischen C++ und einer dir besser vertrauten Sprache unterschätzt? Das geht nämlich vielen Anfängern so...

    Ich versuche ja, die Probleme zu lösen, um die Sprache besser zu verstehen. Speicherverwaltung bereitet mir noch große Schwierigkeiten.

    krümelkacker schrieb:

    Für weitere Tipps fehlt da jetzt der Kontext. Im Code sehe ich zB nirgends eine Liste.

    Ich bin nicht ganz sicher, welche Informationen im Kontext noch gebraucht werden, ich wollte die Informationen möglichst auf das Wesentliche beschränken.

    Mal ein Überlick der Umgebung:

    Das Problem befindet sich in der Methode bool Scene::config( SDL_Event event ). Diese wird in einem While-Loop von der main-Funktion aus aufgerufen.

    Die Funktion beginnt mit einem

    if (!texLoaded_)
    {
        //CODE
    
        texLoaded_ = true;
    }
    

    texLoaded_ ist eine bool-Variable. In diesem Codeteil werden Laufzeit-Variablen definiert, darunter auch die Buttons und die Klassenvariable bNo_, die die Anzahl an Buttons enthält.

    bNo_            = std::distance(button_.begin(), buttonIt_);
    

    im Laufe dieser Funktion gibt es außerdem 2 for-Schleifen, in denen ebenfalls

    int i = std::distance(button_.begin(), buttonIt_)
    

    aufgerufen wird. i ist also nur von kurzer Lebensdauer.

    Kommentiere ich diese Funktion in den for-loops aus, crasht das Programm nicht und ersetze ich die Definition von bNo_ durch

    bNo_            = 0;
    

    kommt es ebenfalls zu keinen Crashs.

    Falls sonst noch etwas notwendig ist, bitte fragen.

    EDIT:
    Button_Panel ist eine simple selbstgeschriebene Klasse, die ein simples Quad darstellt, das mit OpenGL gerendert werden kann und ein paar bools und Funktionen a là selected_ und getCollision() enthält.



  • "Kontext" heißt nicht, die einzelnen Fragmente auseinanderzureißen und getrennt zu zeigen. Wir können dir besser helfen, wenn wir den Code am Stück sehen können. Also schmeiß alles aus der Funktion raus, was für das Problem unwichtig ist (wenn der Fehler dabei verschwindet, hast du die richtige Stelle gefunden) und poste dann mal die gesamte Funktion.

    PS: Wurde der Iterator eigentlich initialisiert, bevor du bNo_ berechnet hast? Wenn ja, zeigt er in den selben Container?



  • CStoll schrieb:

    "Kontext" heißt nicht, die einzelnen Fragmente auseinanderzureißen und getrennt zu zeigen. Wir können dir besser helfen, wenn wir den Code am Stück sehen können. Also schmeiß alles aus der Funktion raus, was für das Problem unwichtig ist (wenn der Fehler dabei verschwindet, hast du die richtige Stelle gefunden) und poste dann mal die gesamte Funktion.

    bool Scene::config( SDL_Event event )
    {
        if (!texLoaded_)
        {
            //TEXTURES
    
            //TEXT
    
            //BUTTONS
            int bNo = 0;
            button_.clear();
            Panel_Button tempbutton1(++bNo,360,360,110,32); // Abbrechen
            button_.push_back(tempbutton1);  
            Panel_Button tempbutton2(++bNo,490,360,105,32);         // Speichern TODO
            button_.push_back(tempbutton2);  
    
            buttonIt_       = button_.end();
            bNo_            = std::distance(button_.begin(), buttonIt_);//<-----
            activeButton_   = 0;
    
            //MUSIC
    
            //SOUNDS
    
            //RUNTIME VARIABLES
            index_          = 0;
            counter_        = 0;
            events_         = true;
            activeButton_   = 0;
    
            //COMMANDS
    
            texLoaded_ = true;
            std::cout << "Scene Configuration Created!" << std::endl;
    
        }
    
        //-------
        //-EVENTS
        //-------
        if ( events_ == true )
        {
            while ( SDL_PollEvent(&event) )
            {
                switch(event.type)
                {
                    case SDL_QUIT:
                        index_ = -1;
                        std::cout << "Closing Programm!" << std::endl;
                        break;
    
                    case SDL_MOUSEMOTION:
                        mouseX_ = event.motion.x;
                        mouseY_ = event.motion.y;
                        for (   buttonIt_  = button_.begin();
                                buttonIt_ <= button_.end();
                                ++buttonIt_ )
                        {
                            // Umwandeln Iterator -> Integer
                            int i = std::distance(button_.begin(), buttonIt_); //<-----
    
                            if ( button_[i].getCollision(mouseX_,mouseY_) )
                            {
                                activeButton_ = i;
                            }
                        }
                        break;//TODO
    
                    case SDL_KEYDOWN:
                        // Diverse Keys
                        break;
    
                            default:
                                break;
                        }
                        break;
    
                }
            }
        }
    
        std::cout << "Events passed" << std::endl;
    
        //-------
        //-LOGIC-
        //-------
        switch( index_ )
        {
            //--0//
            case 0:
                if ( fg_.fadeOut(1) )   // Fade in Forground
                {
                    index_++;
                }
                break;
    
            //--1//
            case 1:
                break;
    
            //END//
            default:
                // Programm schließen
    
        }
    
        // Set active Button
    
        for (   buttonIt_  = button_.begin();
                buttonIt_ <= button_.end();
                ++buttonIt_ )
        {
            int i = std::distance(button_.begin(), buttonIt_); //<-----
            button_[i].setSelected(false);
        }
        button_[activeButton_].setSelected(true);
    
        std::cout << "Logic passed" << std::endl;
    
        //-------
        //-RENDER
        //-------
        renderBegin(WINDOW_WIDTH, WINDOW_HEIGHT);
    
        std::cout << "Render Begin passed" << std::endl;
    
        //BG
        bg_.draw();
    
        //TEXT
        //Speichern/Abbrechen
        if ( button_[bNo_].getSelected() )
        {
            text_.renderGL("Speichern",490,360,100,0,0,200);
        } else {
            text_.renderGL("Speichern",490,360,5,0,0,200);
        }
        if ( button_[bNo_ - 1].getSelected() )
        {
            text_.renderGL("Abbrechen",360,360,100,0,0,200);
        } else {
            text_.renderGL("Abbrechen",360,360,5,0,0,200);
        }
    
        //Überschrift
        text_.setSize(30);
        text_.renderGL("Einstellungen",20,128,5,0,0,200,"bold");
    
        //FG
    
        //Render-Ausklang
        glPopMatrix();                      // stop  rendering phase
    
        SDL_GL_SwapBuffers();               // Render
    
        std::cout << "Render passed" << std::endl;
    
        return true;
    }
    

    CStoll schrieb:

    PS: Wurde der Iterator eigentlich initialisiert, bevor du bNo_ berechnet hast? Wenn ja, zeigt er in den selben Container?

    Er ist in der scene.h initialisiert.
    Erstmals genutzt wird er vor der Berechnung.

    buttonIt_       = button_.end();
    bNo_            = std::distance(button_.begin(), buttonIt_);
    


  • Nach dreimal durchlesen habe ich endlich das Problem lokalisiert (hoffe ich):

    buttonIt_       = button_.end();
    bNo_            = std::distance(button_.begin(), buttonIt_);
    //aka bNo_ = button_.size()
    ...
    if(button_[bNo_].getSelected())
      ...
    

    bNo_ ist der Index von end() und der zeigt hinter das letzte Vector<>-Element. Damit liest du über das Ende deiner Nutzdaten hinaus.

    btw, dir ist schon klar, daß du die Iteratoren auch direkt nutzen kannst, ohne sie unbedingt in Indizes umrechnen zu müssen?
    z.B.:

    for (   buttonIt_  = button_.begin();
                buttonIt_ <= button_.end();
                ++buttonIt_ )
        {
            int i = std::distance(button_.begin(), buttonIt_); //<-----
            button_[i].setSelected(false);
        }
    
    // ==>
    
        for (   buttonIt_  = button_.begin();
                buttonIt_ <= button_.end();
                ++buttonIt_ )
        {
            buttonIt_->setSelected(false);
        }
    

    (und anstelle von end()-begin() (bzw. distance(begin(),end())) kannst du auch size() verwenden, um die Elementzahl zu bestimmen)

    PS: Wenn du die Iteratoren nur lokal benötigst, solltest du sie auch nicht als global verfügbare Variablen mit herumschleppen.



  • CStoll schrieb:

    Nach dreimal durchlesen habe ich endlich das Problem lokalisiert (hoffe ich):

    buttonIt_       = button_.end();
    bNo_            = std::distance(button_.begin(), buttonIt_);
    //aka bNo_ = button_.size()
    ...
    if(button_[bNo_].getSelected())
      ...
    

    bNo_ ist der Index von end() und der zeigt hinter das letzte Vector<>-Element. Damit liest du über das Ende deiner Nutzdaten hinaus.

    bNo_ = button_.size();
    

    macht es leider nicht besser. Das Programm verhält sich nicht anders.

    Im Fall, dass es einfriert, wird die Funktion ein paar mal ausgeführt und stoppt zwischen

    std::cout << "Render Begin passed" << std::endl;
    

    und

    std::cout << "Render passed" << std::endl;
    

    CStoll schrieb:

    btw, dir ist schon klar, daß du die Iteratoren auch direkt nutzen kannst, ohne sie unbedingt in Indizes umrechnen zu müssen?
    z.B.:

    for (   buttonIt_  = button_.begin();
                buttonIt_ <= button_.end();
                ++buttonIt_ )
        {
            int i = std::distance(button_.begin(), buttonIt_); //<-----
            button_[i].setSelected(false);
        }
    
    // ==>
    
        for (   buttonIt_  = button_.begin();
                buttonIt_ <= button_.end();
                ++buttonIt_ )
        {
            buttonIt_->setSelected(false);
        }
    

    Danke, diese Schreibweise ist wirklich komfortabler, habe gar nicht daran gedacht. 🙂



  • Ki schrieb:

    CStoll schrieb:

    Nach dreimal durchlesen habe ich endlich das Problem lokalisiert (hoffe ich):

    buttonIt_       = button_.end();
    bNo_            = std::distance(button_.begin(), buttonIt_);
    //aka bNo_ = button_.size()
    ...
    if(button_[bNo_].getSelected())
      ...
    

    bNo_ ist der Index von end() und der zeigt hinter das letzte Vector<>-Element. Damit liest du über das Ende deiner Nutzdaten hinaus.

    bNo_ = button_.size();
    

    macht es leider nicht besser. Das Programm verhält sich nicht anders.

    Der Wert ist ja der selbe. In einem Array oder vector<> mit size Elementen kannst du die Elemente a[0] bis a[size-1] verwenden, der Zugriff auf a[size] ist undefiniert - und genau das machst du dort.



  • CStoll schrieb:

    Ki schrieb:

    CStoll schrieb:

    Nach dreimal durchlesen habe ich endlich das Problem lokalisiert (hoffe ich):

    buttonIt_       = button_.end();
    bNo_            = std::distance(button_.begin(), buttonIt_);
    //aka bNo_ = button_.size()
    ...
    if(button_[bNo_].getSelected())
      ...
    

    bNo_ ist der Index von end() und der zeigt hinter das letzte Vector<>-Element. Damit liest du über das Ende deiner Nutzdaten hinaus.

    bNo_ = button_.size();
    

    macht es leider nicht besser. Das Programm verhält sich nicht anders.

    Der Wert ist ja der selbe. In einem Array oder vector<> mit size Elementen kannst du die Elemente a[0] bis a[size-1] verwenden, der Zugriff auf a[size] ist undefiniert - und genau das machst du dort.

    Ahhhh, verstehe. 😃

    Danke für die Erklärung, ich hätte mir vielleicht mal den Integer ausgeben lassen sollen. ^^



  • Ich möchte nochmal an diverse Debug-Modi erinnern, die das sofort aufgedeckt hätten.


Anmelden zum Antworten