std::set +find +Eigenes Funktionsobjekt +Speicherzugriffsfehler



  • Hi,
    Ich habe in einer Klasse die
    std::set my_set verwendet. Ich übergebe ein Funktionsobjekt, welches
    den Kontainer ordnet beim einfügen.
    Wenn ich nun mit my_set.find( ...) einen Eintrag suche,
    bekomme ich einen Speicherzugriffsfeher, welchen ich mir nicht erklären kann.
    Der typ der liste ist ein pointer wenn das ev. wichtig ist.
    Also den iterator, welcher find() zurückgeben sollte wird nicht verwendet.
    Ich rufe nur die Funktion find auf.
    Kann es sein, dass find nur auf bestimmt geordneten in diesem Fall Sets funktioniert ?? Also ist Meine Ordnung ev. nicht find kompatiebel ??
    Oder muß ich den Fehler irgendwo anderst suchen.

    Gruß



  • Es wäre praktisch, wenn du ein reales Beispiel posten könntest, wo das passiert. Reduzier dein Programm mal soweit, dass du es (ansonsten lauffähig) hier posten kannst.



  • Hi drakon,
    Habe gerade getestet, ob es ohne das Funktionsobjekt geht.
    Und tatsächlich funktioniert es. Die Funktion find ist abhängig von der ordnung der Elemente in set. Ich glaub ich kotz. Ich kann mir ja vorstellen, dass
    die Implementierung von set dadurch sehr effizient ist, aber
    dann sollte man standardmäßig dazuschreiben (bei der doku) wie find sucht.

    template <typename T>
    class WE_Algo : public WingedEdge<T>
    {.
    .
    .
    .
    .
    //Nicht wundern dass cih nicht einen queue voon std nehme, der geht hier nicht
    std::set< VList<T> *,EventLineOrder<VList<T> * > >    event_queue;
    .
    .
    //wird hier in eine rfunktion aufgerufen, ist aber member dieser klasse.
    //Deswegen stehts hier
    event_queue.find(item);
    .};
    
    //das Funktionsobjekt zum ordnen
    
    template <typename T>
    class EventLineOrder : private std::binary_function<T,T,bool>
    {
    .
    .
    inline bool operator () (const T &LeftValue, const T &RightValue)
            {
                for(unsigned int x=Dimension-1;x>=0;x--)
                    if(LeftValue->V[x] < RightValue->V[x])
                        return false^!(x%2);
                    else if(LeftValue->V[x] > RightValue->V[x])
                        return true^!(x%2);
    
                //If the Points are the same,
                return true;
            }
    .
    }
    
    int main(void)
    {
    .
    .
    WE_Algo<long double> a;
    

    Also aus main raus wird eine funktion von WE_Algo aufgerufen, welche wiederum find aufruft.
    Mit dem Funktionsobjekt, werden die Daten richtig geordnet, find steigt aber aus,
    Ohne sind die daten falsch, find funktioniert aber.
    Gruß



  • Ein Punkt ist, dass ein unsigned int per Definition >= 0 ist. Dann, ändert sich die Reihenfolge der Elemente zur Laufzeit? Objekte eines Set müssen konstant sein, zumindest die Teile, die als Schlüssel verwendet werden.


  • Mod

    for(unsigned int x=Dimension-1;x>=0;x--)
    

    kann nicht aufgrund der Schleifenbedingung terminieren, und sobald der Überlauf da ist (das passiert genau dann, wenn zwei Elemente äquivalent sind...), dürfte ein Zugriffsfehler folgen. Eine so dekrementierende Schleife muss das Dekrementieren an den Anfang stellen:

    for(unsigned int x=Dimension;x-- >0;)
    


  • 🙂
    @LordJaxom && Camper
    Danke für den Hinweis. Ich habs und habs nicht gefunden=(
    Gruß



  • Diesen Fehler hättest du sehr gut alleine finden können.

    1. Du hättest den Debugger benutzen können, dann hättest du gemerkt, dass du einfach nicht aus der Schleife kommst.

    2. Du hättest wirklich mal ein Minimalbeispiel von deiner Situation machen können, welches natürlich (aufgrund der vereinfachten Vergleichsfunktion) geklappt hätte. Somit hättest du dann schon gewusst, dass es prinzipiell funktioniert. Und dann wäre es nicht mehr lange genangen, dass du bei der Implementierung der Vergleichsfunktion misstrauisch geworden wärst und da nochmal nachgehackt hättest, weil sonst ja nichts grossartig anderst ist..

    @LordJaxom:
    Ehrlich gesagt verstehe ich deinen Gedankengang nicht ganz.

    Ein Punkt ist, dass ein unsigned int per Definition >= 0 ist. Dann, ändert sich die Reihenfolge der Elemente zur Laufzeit? Objekte eines Set müssen konstant sein, zumindest die Teile, die als Schlüssel verwendet werden.

    Was hat hier unsigned int mit der Reihenfolge zu tun? Und geändert wird die Reihenfolge ja "ständig", respektive wenn es nötig ist wenn ein neuer Eintrag gemacht wird. Und in wie fern muss ein set konstant sein? - Und speziell, wie kann lediglich ein Teil davon konstant sein? Und als Schlüssel und gleichzeitig Value werden ja alle Einträge behandelt..

    Verstehe ich dich einfach falsch, oder hast du da eine andere Datenstruktur im Kopf?



  • @ Drakon
    Mein debugger ist heut eigenwillig. Er will heut nicht. ich weiß auch nicht wiso.
    Ich habe lange gesucht bevor ich gepostet habe. Solch fehler finde ich normal.
    Aber dieses mal nicht.
    War scheiße, merke ich selbst ne 😉



  • War ja nicht so direkt, als Vorwurf gedacht, sondern nur um zu zeigen, was halt wirklich oft hilft. Oft wissen die Leute gar nicht, was ein Debugger ist. 😉



  • LordJaxom hat ein Fragezeichen hinten an den Satz gehängt 🙂
    Ich habe geschrieben , dass ich der Auffassung bin, dass find von
    der Ordnung der Elemente abhängt. Er war so freundlich das auf zu nehmen, und sich gedanken darüber zu machen. Er hat mir erklärt, dass
    die Elemente nicht verändert werden dürfen, da sonst find aussteigen könnte.
    Es wäre ja möglich, dass außer der schleife noch ein weiterer fehler wäre.
    So habe ich das zumindest verstanden.
    Gruß



  • @Drakon
    🙂 Ich benutze meinen debugger zwar, aber so wirklich gut kennen tue ich ihn tatsächlich nicht.
    Er zickt öfter.
    Darf ich fragen mit was du entwickelst ==
    Gruß



  • Ich benutze Visual Studio 2008. (die Express Versionen sind auch zu empfehlen).



  • Die Express-Version von MSVC++ kannst du gratis herunterladen. Der Debugger ist wirklich sehr gut, den kann ich ebenfalls empfehlen (sowie die gesamte IDE). Vorausgesetzt, du arbeitest unter Windows.



  • 🙂 Plattform Werbung.
    Ich glaub ihr bezieht schmiergelder *ggg*
    Im Ernst. Habe mit Visual Studio .NET auch schon programmiert,
    und finde die Entwicklungsumgebung richtig gut.
    Aber ich Entwickle unter Linux. Als IDE habe ich mir CODE::BLOCKS
    kompiliert. Der debugger nervt.
    Ist hier eher Windows oder linux Fraktion ??

    Gruß



  • VS ist imo unter Windows das beste, was man machen kann. 😉

    Ich kenne jetzt keine genauen Zahlen, aber ich denke, dass hier eher VS vorherrscht..



  • Seufz..... Alle Macht dem Pinguin *lach*
    Na ja bin kein Fanatiker.

    //---------------------------------------------------------------------

    Was ich noch zum Thema schreiben wollte ist, dass Find nur funktioniert, wenn
    die Ordnungsfunktion bei Gleichheit False zurück gibt.
    Ansonsten findet finde nie ein Objekt.
    Also das letzte false ist noch ausschlaggebend.
    (Nicht dass ein anonymer Leser das verfolgt, und dann entteuscht ist dass es nicht funktioniert wie behauptet).

    inline bool operator () (const T &LeftValue, const T &RightValue)
            {
                for(unsigned int x=Dimension;x-- >0;)
                {
                    if(LeftValue->V[x] < RightValue->V[x])
                        return false^!(x%2);
                    else if(LeftValue->V[x] > RightValue->V[x])
                        return true^!(x%2);
                }
                //If the Points are the same,
                return false;
            }
    


  • @drakon:
    "Ein Punkt" und "Dann" sollten andeuten, dass die Anmerkung zu unsigned und die zur Reihenfolge zwei unabhängige Punkte darstellen. Weiterhin (besser als "dann"? :p) müssen die Schlüssel von Maps und Sets konstant sein, sprich die relative Reihenfolge der Elemente darf sich nicht ändern. Beim Set ist das Element selbst der Schlüssel.

    Das weisst Du sicher, aber ich scheine mich gestern etwas undeutlich ausgedrückt zu haben 😉



  • Du meinst:

    inline bool operator () (const T &LeftValue, const T &RightValue) const 
            {
                for(unsigned int x=Dimension;x-- >0;)
                {
                    if(LeftValue->V[x] < RightValue->V[x])
                        return !(x%2);
                    else if(LeftValue->V[x] > RightValue->V[x])
                        return (x%2);
                }
                //If the Points are the same,
                return false;
            }
    

    ???

    Gruß



  • LordJaxom schrieb:

    @drakon:
    "Ein Punkt" und "Dann" sollten andeuten, dass die Anmerkung zu unsigned und die zur Reihenfolge zwei unabhängige Punkte darstellen. Weiterhin (besser als "dann"? :p) müssen die Schlüssel von Maps und Sets konstant sein, sprich die relative Reihenfolge der Elemente darf sich nicht ändern. Beim Set ist das Element selbst der Schlüssel.

    OK. Das mit dem unsigned weiss ich jetzt, was du gemeint hast. Allerdings weiss ich immer noch nicht, was du meinst mit dem, dass die Keys konstant sein müssen.. Man kann da einfügen/löschen, wie man lustig ist. Von Konstanz imo keine Spur..



  • drakon schrieb:

    OK. Das mit dem unsigned weiss ich jetzt, was du gemeint hast. Allerdings weiss ich immer noch nicht, was du meinst mit dem, dass die Keys konstant sein müssen.. Man kann da einfügen/löschen, wie man lustig ist. Von Konstanz imo keine Spur..

    *seufz*

    Kannst Du den Key eines Elements in der Map ändern? Nein, Du musst es, wie Du sagst, löschen und neu einfügen. Ergo sind die Keys konstant. Da in einem Set das Element der Key ist, ist das Element konstant.

    Das wollte ich an dieser Stelle erwähnt haben, da in einem Set von Zeigern ja de Zeiger konstant ist, nicht aber das Bezeigte. Wenn man aber das Bezeigte als Sortierkriterium nutzt, kommt man schnell in Teufels Küche, weil der Compiler nicht warnt, wenn man das Bezeigte ändert.



  • Man kann aber das ordnungskriterium Während dem ordnen Ändern, in dem man den Functor mit

    typename std::multiset< EList<T> *,StatusOrder<EList<T> *,T > >::key_compare        Compare_Functor;
    Compare_Functor=status_tree.key_comp();
    Compare_Functor.setOrder(false);
    

    sofern man im Functor die Funktion setOrder definiert hat:

    template <typename T,typename T2>
    class StatusOrder : private std::binary_function<T,T,bool>
    {
        private:
            bool OrderUp;
        public:
            explicit StatusOrder(bool OrderUpper=true){OrderUp=OrderUpper;};
            void setOrder(bool OrderUpper=true){OrderUp=OrderUpper;};
    

    Das kann die Laufzeit beim suchen verbessern.
    Gruß


Anmelden zum Antworten