STL aus shared object verwenden oder aber alternative zu std::map?
-
Hallo zusammen,
Ich habe ein Problem bei dem ich einfach nicht weiter komme und selbst intensive Recherche nichts gebracht hat.
Folgendes:
1.) Mein Hauptprogramm hält eine Instanz der Klasse MyClass.
2.) Hauptprogramm lädt so(shared objects) Dateien, diese bekommen referenz auf die MyClass Instanz übergeben
3.) In dem so wird dann MyClass::add("key"/*key*/,66/*value*/) aufgerufen.
MyClass add fügt seinerseits einer std::map das Key/Value Paar hinzu.
Alles klappt soweit. bis
4.)Beim Beenden des Programms gibt es "double free" Fehlermeldungen. ich weiß nicht, woher diese kommen.Richtig Skuril wird es jetzt:
Angenommen, die in der im shared object definierte Klasse ist ein Kind der abstrakten Klasse MySO. Das Hauptprogramm lädt dann die shared objects, die die konkreten Implementierungen von MySO enhalten.
Wird MyClass::add("key"/*key*/,66/*value*/) aus einer Methode aufgerufen, die das Hauptprogramm direkt aufuft gibt es diese Fehler nicht.
d.h. bei diesem Beispiel:MySO::doSomething() { call(); } MySO::call() { myClass.add("key"/*key*/,66/*value*/); }
würde es Fehler geben, wenn ich aus dem Hauptprogramm doSomething() aufrufe aber nicht, wenn ich aus dem Hauptprogramm call() aufrufe. Leider ist es mir in der realen Welt nicht möglich das call()-Äquivalent direkt aufzurufen.
Hat jemand eine Idee? Wenn ich die Map Implementierung wechsel (z.B. durch verwendung von QMap aus der Qt-Bibliothek) tritt das Problem nicht mehr auf. Qt darf ich aber leider an der Stelle nicht verwenden. Vllt. gibt es eine Lösung oder aber andere Maps?
Viele Grüße,
Eric
-
Hallo,
Ich verstehe das Problem immer weniger...Im Destruktor der Klasse MyClass (die die std::map beinhaltet habe ich jetzt
mal testweise folgenden code implementiert):// My Map ist ein Typedef, nicht wundern... MyMap::iterator it = m_variantMap.begin(); while (it!= m_variantMap.end()) { std::cout<< "vorher\n"; std::cout<< it->first <<":" << it->second<<"\n"; m_variantMap.erase(it); it++; std::cout<< "nachher\n"; }
Bei dem Beispiel vorhin wäre das erwartete Ergebnis
vorher
key:66
nachhertatsächlich kommt es hierzu:
Bei dem Beispiel vorhin wäre das erwartete Ergebnisvorher
key:66
*** glibc detected *** ../bin/lin/RsmViewer: free(): invalid pointer: 0x08646180 ***Irgendwelche Ideen? Ich bin mit meinem Latein am Ende
Viele Grüße,
Eric
-
probier mal die map so zu loeschen
while( !m_variantMap.empty() ) { std::cerr<< m_variantMap.begin()->first <<":" << m_variantMap.begin()->second<<"..."; m_variantMap.erase( m_variantMap.begin() ); std::cerr <<"OK\n"; }
wenn das auch probleme macht, sind die key val typen irgendwelche objekte die was machen im d'tor?
-
// My Map ist ein Typedef, nicht wundern... MyMap::iterator it = m_variantMap.begin(); // it zeigt auf begin while (it!= m_variantMap.end()) { std::cout<< "vorher\n"; std::cout<< it->first <<":" << it->second<<"\n"; m_variantMap.erase(it); // begin wird gelöscht it++; // it wird auf das dem gelöschten Element folgenden gesetzt (aufgemerkt! hier ist der Wurm!) std::cout<< "nachher\n"; }
Versuch mal:
// My Map ist ein Typedef, nicht wundern... MyMap::iterator it = m_variantMap.begin(); // it zeigt auf begin while (it!= m_variantMap.end()) { std::cout<< "vorher\n"; std::cout<< it->first <<":" << it->second<<"\n"; it = m_variantMap.erase(it); // begin wird gelöscht, erase gibt Iterator aufs nächste gültige Element zurück // it++; nicht mehr erforderlich! std::cout<< "nachher\n"; }
-
Hallo,
vielen Dank für Eure Antworten. Merkwürdigerweise kann ich das Problem hier auf der Arbeit gar nicht mehr reproduzieren.
Hier verwende ich Fedora Core 5, gcc 4.1.1
Zu Hause verwende ich Fedora Core 4 mit einer älteren gcc Version (weiß leider nicht auswendig, welche, aber nicht 4.1.1).
Ich werde also probieren, ob ein Compiler-Update das Problem behebt.Den Code zum Löschen kann ich dann ohnehin verwerfen (der war nur zum Testen). Danke trotzdem!
Viele Grüße,
Eric
-
LordJaxom schrieb:
// My Map ist ein Typedef, nicht wundern... MyMap::iterator it = m_variantMap.begin(); // it zeigt auf begin while (it!= m_variantMap.end()) { std::cout<< "vorher\n"; std::cout<< it->first <<":" << it->second<<"\n"; it = m_variantMap.erase(it); // begin wird gelöscht, erase gibt Iterator aufs nächste gültige Element zurück // it++; nicht mehr erforderlich! std::cout<< "nachher\n"; }
Oder einfach:
while (!m_variantMap.empty()) { MyMap::iterator it = m_variantMap.begin(); std::cout << "vorher\n" << it->first <<":" << it->second<<"\n"; m_variantMap.erase(it); std::cout<< "nachher\n"; }
Das ist natürlch bis auf die Ausgabe gleichbedeutend mit:
m_varianteMap.clear()
Im übrigen sind die Ursache solcher double-free Probleme häufig falsche Kopierkonstruktoren oder Zusweisungsoperatoren. Wenn ich im Destruktor ein delete ausführe und keinen Kopierkonstruktor habe, dann wird die Kopie ein delete auf den selben Pointer ausführen.
Tntnet