void value not ignored as it should be



  • Ich kapiere nicht ganz was hier falsch ist. Ich habe eine Klasse die eigentlich gar nichts macht nur zwei Punkte speichert und einen Stack von eben diesem Klassentyp.

    class Position
    {
    public:
        Position(int inX=0, int inY=0);
        int x;
        int y;
    };
    

    Ich will also den Stack daraufhin prüfen ob er leer ist (ist er aber nicht denn er wird mit push() gefüllt) und bekomme die im Titel genannte Fehlermeldung...

    stack<Position*> st;
    Position* pos = 0;
    
    // push the position on the stack and assign label
    st.push(new Position(x,y));
    labels(x,y) = lab;
    
    while (!(st.empty()))
    {
            pos = st.pop();
            int i = pos->x;
            int j = pos->y;
    }
    

    Was mache ich denn falsch?



  • Hallo

    std::stack::pop() hat void als Rückgabewert.

    bis bald
    akari



  • die Methode pop() loescht nur den obersten Eintrag inm stack und hat Rueckgabewert void. Daher die Fehlermeldung. Zum Lesen des obersten Eintrags dien die Methode top(), richtig waere also:

    stack<Position*> st;
    Position* pos = 0;
    
    // push the position on the stack and assign label
    st.push(new Position(x,y));
    labels(x,y) = lab;
    
    while (!(st.empty()))
    {
            pos = st.top();
            int i = pos->x;
            int j = pos->y;
            //delete pos waere an dieser stelle evtl angebracht - speicherlecks vermeiden!
            st.pop();
    }
    


  • hehe, auf den krempel bin ich auch mal reingefallen 😃 frag mich, wer auf den bolzen gekommen ist, pop keinen rückgabewert zu verpassen und zusätzlich nen top einzubauen. intuitiv ist das nicht.



  • Ist nicht intuitiv, aber nötig, um das ganze Threadsafe zu machen. Wenn pop den Wert zurückgibt, gibt es KEINE Möglichkeit, das komplett Threadsafe zu realisieren.

    Felix



  • Alles klar nun funktioniert es... das ist echt komisch gelöst denn aus Python und Java kenne ich es anders... aber gut nun weiß ich Bescheid.



  • Das ermoeglicht ganz einfach mehrfaches Lesen des obersten Wertes durch einfache top() aufrufe, statt den Wert nach jedem pop() wieder zu pushen...

    Zur Not kann man sich ja ne eigene pop() routine schreiben:

    template<typename T>
    T mypop(std::stack<T> st) {
      T ret = st.top();
      st.pop();
      return ret;
    }
    
    int main()
    {
    std::stack<myClass> st;
    //...
    
    myClass mc = mypop(st); //template parameter von mypop muss nicht angegeben werden, wird aus argument hergeleitet.
    }
    


  • Phoemuex schrieb:

    Ist nicht intuitiv, aber nötig, um das ganze Threadsafe zu machen. Wenn pop den Wert zurückgibt, gibt es KEINE Möglichkeit, das komplett Threadsafe zu realisieren.

    Felix

    hmmm ... ist Threadsafe wirklich das Kriterium ? Ich hätte eher an Exceptionsafe gedacht ....

    Gruß,

    Simon2.



  • Das pop() void als Rückgabewert hat, liegt daran, dass es das Objekt als Kopie zurückgeben muss (weil das eigentliche Objekt zerstört wird). Wenn man nun große Objekte verwaltet und einfach nur das oberste Element löschen will, ohne dieses dann noch weiter zu verwenden, wäre das sehr ineffizient.



  • Jetzt habe ich ein neues Problem. Vielleicht sollte ich mal kurz sagen was ich hier eigentlich tue! 😉
    Also ich schreibe ein Programm das automatisch rote Augen in einem Bild finden soll und diese auf Wunsch auch automatisch korrigiert.
    Dazu nutze ich CImg, um die Pixeloperationen durchzuführen.
    Der vorhin gezeigte Ausschnitt aus dem Algorithmus ist der "Connected Components Labeling"-Abschnitt, hier wird das binarisierte Bild in verschiedene Objekte zerlegt.
    Bei einem Bild der Größe 800x600 funktioniert das auch alles noch, aber bei größeren Bildern bricht das Programm mit einem "Segmentation Fault" ab. Nun weiß ich nicht warum. Ich denke es liegt am Stack, denn wenn ich nicht mehr auf den Stack pushe dann bricht es auch nicht ab.
    Hat ein Stack eine Begrenzung?

    Hier mal der Code, der abbricht:

    CImg<imgType> EyeLocatorPriv::labelImage()
    {
        CImg<imgType> labels(width,height,1,1);
        labels.fill(0);
        stack<Position*> st;
        Position* pos = 0;
        int lab = 1;
    
        for (int x=1; x<width-1;x++)
        {
            for (int y=1; y<height-1; y++)
            {
                if (redBinaryMask(x,y) == 0)
                    continue;
                if (labels(x,y) > 0)
                    continue;
                // push the position on the stack and assign label
                st.push(new Position(x,y));
                labels(x,y) = lab;
    
                while (!st.empty())
                {
                    pos = st.top();
                    st.pop();
                    int i = pos->x;
                    int j = pos->y;
    
                    if (redBinaryMask(i-1,j-1) == 255 && labels(i-1,j-1) == 0)
                    {
                        st.push(new Position(i-1,j-1));
                        labels(i-1,j-1) = lab;
                    }
    
                    if (redBinaryMask(i-1,j) == 255 && labels(i-1,j) == 0)
                    {
                        st.push(new Position(i-1,j));
                        labels(i-1,j) = lab;
                    }
    
                    if (redBinaryMask(i-1,j+1) == 255 && labels(i-1,j+1) == 0)
                    {
                        st.push(new Position(i-1,j+1));
                        labels(i-1,j+1) = lab;
                    }
    
                    if (redBinaryMask(i,j-1) == 255 && labels(i,j-1) == 0)
                    {
                        st.push(new Position(i,j-1));
                        labels(i,j-1) = lab;
                    }
    
                    if (redBinaryMask(i,j+1) == 255 && labels(i,j+1) == 0)
                    {
                        st.push(new Position(i,j+1));
                        labels(i,j+1) = lab;
                    }
    
                    if (redBinaryMask(i+1,j-1) == 255 && labels(i+1,j-1) == 0)
                    {
                        st.push(new Position(i+1,j-1));
                        labels(i+1,j-1) = lab;
                    }
    
                    if (redBinaryMask(i+1,j) == 255 && labels(i+1,j) == 0)
                    {
                        st.push(new Position(i+1,j));
                        labels(i+1,j) = lab;
                    }
    
                    if (redBinaryMask(i+1,j+1) == 255 && labels(i+1,j+1) == 0)
                    {
                        st.push(new Position(i+1,j+1));
                        labels(i+1,j+1) = lab;
                    }
                } // end while
                lab++;
            }
        }
        components = lab;
        return labels;
    }
    

    Was kann denn das sein? Läuft der Stack einfach voll? Das wäre aber doof weil normalerweise sind meine digitalen Fotos alle so 3008x2272px groß...
    Jemand eine Idee?



  • Laut einem meiner Bücher soll man in STL-Containern keine Zeiger, sondern normale Objekte abspeichern, da die Container intern Objekte verschieben, kopieren, usw. und es deswegen zu Fehlern kommen kann. Probier doch mal den Algorithmus mit stack<Position> (ohne Zeiger). Vielleicht löst das dein Problem. Außerdem ersparst du dir dann das explizite Freigeben der Zeiger.



  • XMaster schrieb:

    Laut einem meiner Bücher soll man in STL-Containern keine Zeiger, sondern normale Objekte abspeichern, da die Container intern Objekte verschieben, kopieren, usw. und es deswegen zu Fehlern kommen kann.

    Das wundert mich nu ein wenig. Wenn man Container mit Zeigern benutzt, werdne ja nur die Zeiger verschoben udn kopiert, was eigentlich kein Problem sein sollte. Die Objekte die dahinter stecken, bleiben ja unberuehrt.
    Ausserdem, wenn Container mit Zeigern pfui sind, wie soll man dann folgendes behandeln:
    - Sammlungen von abgeleiteten Objekten der selben Basisklasse (Stichwort Polymorphie)
    - Sammlungen von nicht-kopierbaren Objekten

    In beiden Faellen erscheinen mir Container mit Zeigern als die natuerliche Loesung, vorausgesetzt man schafft keine Speicherlecks...



  • XMaster schrieb:

    Laut einem meiner Bücher soll man in STL-Containern keine Zeiger, sondern normale Objekte abspeichern, ...

    Das hast Du vermutlich mißverstanden. Ich denke mal, dass dort geraten wird, "... keine Zeiger auf Objekte im Container anzulegen ..."
    Das hat im Deutschen eine fiese Doppeldeutigkeit: Ich klammere mal:
    "... keine (Zeiger auf Objekte) im Container anzulegen ..." (= etwas im Container ablegen)
    "... keine Zeiger auf (Objekte im Container) anzulegen ..." (= Zeiger auf etwas anzulegen)

    Vergleich:
    A) "... (Zeiger auf Objekte) im Container ..."

    vector<myType*> vec(2); // Vector von Zeigern auf myType
    
                            // x     &x       vec[1]   &vec[1]
                            // --------------------------------
    myType x('S');          // 'S'   0x1234   0x0000   0xaffe   
    vec[1] = &x;            // 'S'   0x1234   0x1234   0xaffe   
    vec.resize(2000);       // 'S'   0x1234   0x1234   0xdead
    
    // => selbst wenn die Zeiger in vec verlagert werden, behalten sie doch dieselben Wert
    // => sie zeigen weiterhin dahin, wo sie sollen
    // => OK
    

    😎 "... Zeiger auf (Objekte im Container) ..."

    vector<myType> vec(2);  // Vector von myType-Objekten
    
                            // x     &x       vec[1]   &vec[1]   p
                            // -------------------------------------
    myType x('S');          // 'S'   0x1234   0        0xaffe    -
    vec[1] =  x;            // 'S'   0x1234   'S'      0xaffe    -
    myType* p = &vec[1];    // 'S'   0x1234   'S'      0xaffe    0xaffe
    vec.resize(2000);       // 'S'   0x1234   'S'      0xdead    0xaffe
    
    // => Nach der Verlagerung hat zwar vec[1] noch denselben Wert (Kopiert von x) aber eine andere Adresse
    // => p zeigt weiterhin auf 0xaffe, aber vec[1] liegt inzwischen auf 0xdead
    // => DANGER !!!
    

    Gruß,

    Simon2.



  • XMaster schrieb:

    Laut einem meiner Bücher soll man in STL-Containern keine Zeiger, sondern normale Objekte abspeichern, da die Container intern Objekte verschieben, kopieren, usw. und es deswegen zu Fehlern kommen kann. Probier doch mal den Algorithmus mit stack<Position> (ohne Zeiger). Vielleicht löst das dein Problem. Außerdem ersparst du dir dann das explizite Freigeben der Zeiger.

    Mal abgesehen von der expliziten Freigabe ist diese Aussage humbug (in welchem Buch steht die?). Container von Zeigern sind aus den von pumuckl genannten Gründen durchaus gängig.

    Eine Alternative wären die pointer container in boost, welche sich selbst um die Freigabe der Zeiger kümmern, oder das speichern von boost smart pointern in einem Standardcontainer.



  • Wenn ich keine Zeiger nutze, kann ich doch auch keine Objekte dynamisch anlegen (das muss ich aber)...
    Meint ihr ich sollte mal boost installieren und die dortigen Container einsetzen?



  • TheGrudge schrieb:

    Wenn ich keine Zeiger nutze,...

    Lies nochmal !
    Deine Prämisse bezieht sich hier auf eine These, der schon massiv widersprochen wurde.

    Gruß,

    Simon2.



  • Simon2 schrieb:

    Phoemuex schrieb:

    Ist nicht intuitiv, aber nötig, um das ganze Threadsafe zu machen. Wenn pop den Wert zurückgibt, gibt es KEINE Möglichkeit, das komplett Threadsafe zu realisieren.

    Felix

    hmmm ... ist Threadsafe wirklich das Kriterium ? Ich hätte eher an Exceptionsafe gedacht ....

    Gruß,

    Simon2.

    Du hast natürlich recht 👍 Gut, wenn man immer jemanden hat, der einen korrigiert 😃

    Felix



  • Ja schon klar das dies wohl nix damit zu tun hat, ich wollte ja nur erklären warum ich Zeiger nutze. Trotzdem löst das nicht mein Problem, ich verstehe einfach nicht wieso ich einen Segmentation Fault bekomme.



  • Phoemuex schrieb:

    ...
    Du hast natürlich recht 👍 Gut, wenn man immer jemanden hat, der einen korrigiert 😃

    Felix

    Gut ! Ich hatte schon einen Knoten im Gehirn, weil ich dachte, ich wäre zu blöd.

    Danke für die Rückmeldung, 👍

    Simon2.



  • Ok ich habe nun raus gefunden, das es wohl nicht an der Bildergröße liegt (also kein Speicherüberlauf), denn es gehen auch manche Bilder nicht, die nur 300x240px groß sind (oder andere Dimensionen).
    Was kann denn das verursachen? Irgendwie ist die Fehlermeldung "Segmentation Fault" wirklich nicht sehr aussagekräftig... Wie könnte ich denn das debuggen? Ich komme normal von Python her und ich weiß nun nicht wie ich da rangehen soll... bei Python bekommt man eigentlich immer aussagekräftige Exceptions.



  • OK ich habe mittlerweile mit GDB raus gefunden, das es wohl Zugriffsprobleme gibt bei manchen Bildern, warum weiß ich aber nicht.
    Nun habe ich mal Valgrind installiert, aber ich habe nicht wirklich den Plan was ich damit machen kann.
    Immerhin startet nun das Programm wenn es mit valgrind aufgerufen wird, aber das ist ja keine Lösung 😉

    Hier mal die Ausgabe: http://rafb.net/p/MH74yY52.html

    Ich hoffe ihr könnt damit was anfangen, wie gesagt ich bin Python verwöhnt und dort gibt es ja Garbage Collectors, vielleicht ist das ja mein Problem...


Anmelden zum Antworten