hash_map: Elemente freigeben



  • Ich habe ein ganz merkwürdiges Problem:

    struct equal
    {
      bool operator()(const char* s1, const char* s2) const
      {
        return strcmp(s1, s2) == 0;
      }
    };
    
    typedef std::hash_map<const char*, TBasicProductItem*, std::hash<const char*>, equal> ProductMap;
    
    ProductMap::iterator it = prMap.begin(); // prMap ist eine ProductMap
    while (it != prMap.end()) {
      delete it->second;
      ++it;
    }
    

    Mein Problem: it ist niemals == prMap.end(). Er läuft über das Ende hinaus und dann gibts logischerweise eine Zugriffsverletzung. Ich verstehe nicht warum das so ist. Ist vielleicht am delete etwas faul? Wenn ich das weglasse, läuft er nicht zu weit.

    Weiß jemand da Rat?



  • Äh.
    std::hash<const char*> wird wohl die Adresse hashen und nicht den Inhalt. Ich denke nicht dass das gewollt ist.

    Und wieso nimmst du nicht einfach std::string stattdessen?

    Nochwas: wenn der C-String auf den diese "const char*" zeigen ein Teil von TBasicProductItem ist dann ist da ganz klar "beim delete was faul", da du der map dann ja die Keys unterm Hintern weglöscht. Und: sollte der als Key verwendete C-String in TBasicProductItem zuhause sein, dann verwende doch einfach ein hash_set anstelle der hash_map. Nicht?



  • Es hat schon seine Gründe, warum ich einen C-string benutze. Er zeigt übrigens nicht auf etwas innerhalb von TBasicProductItem. Das Hashen des const char* und der Zugriff mit string-Literalen funktionieren auch. Mehrfach getestet.

    Irgendwie kommt der Iterator durch das delete durcheinander in der Schleife durcheinander.

    Noch bin ich ratlos...

    Keep smilin!
    vi.p



  • Nein, das hashen funktioniert nicht, glaube es mir.



  • Wieso? Gibt es keine Spezialisierung der has_map für const char* ??



  • Hallo hustbaer!

    Mag sein, das du recht hast. Allerdings scheint das Problem dennoch woanders zu liegen. Ich habe nämlich testhalber mal die hash_map gegen eine normale map ausgetauscht. Das gleiche Ergebnis.

    Keep smilin'
    vi.p



  • .... ich habe zuwenig gelesen - sorry.



  • Na, jetzt hast du es ja schon gelöscht...

    Aber du hattest irgendwie doch recht. Bzw. brachte mich das auf den richtigen Gedanken.
    Habe Jetzt mal statt const char* einen String (C++Builder) benutzt und die hash_map durch eine map ersetzt. So funktioniert es.
    Ich würde aber dennoch gerne eine hash_map benutzen, weil schneller. Wie muss eine hash-Funktion aussehen? Kann mir da jemand einen Tip geben

    Sorry an hustbaer und Simon2 für die falschen Behauptungen.

    Keep smilin'
    vi.p



  • Du brauchst eine Hash-Funktion, die den Inhalt des Strings verrechnet (z.B. die ersten vier Bytes als int-Wert zusammengefasst, eine XOR-Kombination aller Zeichen oder im allgemeinen Fall h(x)=Sum(i=0..x.length()-1) k[i]*x[i] (woher du die Koeffizienten k[i] bekommst, mußt du selber wissen)).



  • vi.p schrieb:

    Na, jetzt hast du es ja schon gelöscht...

    Aber du hattest irgendwie doch recht. ...

    Naja - ich hatte einfach übersehen, dass Du ja eine maßgeschneiderte equals()-Funktion mitgeliefert hast.
    Damit passte mein Beispiel nicht mehr ... und da ich kurz weg musste, bevor ich das prüfen konnte, habe ich lieber mein unpassendes gelöscht, um Dich nicht auf die falsche Fährte zu schicken. Inwieweit mein Tipp trotzdem hilfreich gewesen sein könnte, weiß ich noch nicht, aber ich schaue mir das Ganze nochal an.

    Gruß,

    Simon2.



  • Simon2 schrieb:

    Inwieweit mein Tipp trotzdem hilfreich gewesen sein könnte, weiß ich noch nicht, aber ich schaue mir das Ganze nochal an.

    Er hat(te) zwar eine selbstgeschriebene equals-Funktion, aber die "normale" Hash-Funktion (und die geht üblicherweise genausowenig auf den Inhalt hinter dem char* ein wie der operator<).



  • CStoll schrieb:

    Simon2 schrieb:

    Inwieweit mein Tipp trotzdem hilfreich gewesen sein könnte, weiß ich noch nicht, aber ich schaue mir das Ganze nochal an.

    Er hat(te) zwar eine selbstgeschriebene equals-Funktion, aber die "normale" Hash-Funktion (und die geht üblicherweise genausowenig auf den Inhalt hinter dem char* ein wie der operator<).

    Ahaaa !!!

    Ich war gerade auf der Suche, wie denn std::hash_map und std::hash funktionieren. in "meinem" Standard finde ich die jedenfalls nicht. Gehört das zu "dem TR1-Zeugs" ?

    Gruß,

    Simon2.



  • Nein, das dürfte eine MS-eigene Bastelei sein (wobei die Frage offen bleibt, warum jemand nicht-standardisierte Klassen in den Namensraum 'std' packt). Aber ich hab' mich selber mal intensiver mit Hash-Containern beschäftigt - und dort endet die Standard-Implimentierung meist bei size_t hash(T value){return static_cast<size_t>(value);} (bzw. äquivalenten Lösungen).



  • CStoll schrieb:

    Nein, das dürfte eine MS-eigene Bastelei sein (wobei die Frage offen bleibt, warum jemand nicht-standardisierte Klassen in den Namensraum 'std' packt)....

    Ach sh*t !! Da falle ich jedesmal wieder drauf rein !

    Danke,

    Simon2.



  • Simon2 schrieb:

    Ich war gerade auf der Suche, wie denn std::hash_map und std::hash funktionieren. in "meinem" Standard finde ich die jedenfalls nicht. Gehört das zu "dem TR1-Zeugs" ?

    Ich benutze hier den C++Builder 6 mit der STL von STLport. Ich weiß, dass hash_map nicht Standard ist, aber wenn sie da ist, warum nicht benutzen.

    Habs jetzt mit entsprechender Hash-Funktion zum Laufen gebracht.



  • vi.p schrieb:

    Simon2 schrieb:

    Ich war gerade auf der Suche, wie denn std::hash_map und std::hash funktionieren. in "meinem" Standard finde ich die jedenfalls nicht. Gehört das zu "dem TR1-Zeugs" ?

    Ich benutze hier den C++Builder 6 mit der STL von STLport. Ich weiß, dass hash_map nicht Standard ist, aber wenn sie da ist, warum nicht benutzen....

    Neee - darfst Du gerne machen und ist auch sinnvoll. Ich persönlich finde halt nicht so schön, den Namensraum std mit Eigenem zu füllen. Spezialisierungen/Overloads mögen noch angehen, aber komplett neue Funktionalitäten ... das gefällt mir nicht so, weil es einfach den Eindruck der "Standardisiertheit" erweckt, der einfach nicht gegeben ist.
    Ebensowenig würde ich dazu raten, Selbstgeschriebenes im namespace "windowsxp" oder "MS" unterbringen....

    Bei mir war nur das Problem, dass ich mal nachsehen, wollte, wie die funktionieren ("Man lernt nie aus !" 😉 ) .... und es nirgendwo gefunden habe.

    Gruß,

    Simon2.


Log in to reply