free(): invalid pointer



  • Hallo Zusammen,

    bevor jetzt jemand sagt, ich gebe gebe eine Speicheradresse frei, die schon mal frei gegeben wurde oder noch nicht reserviert wurde, das trifft definitiv nicht zu. Die Erklärung kommt später.
    Ich habe Daten im STL Container map, die ich mit der folgenden Zeile anlege:

    somethingMap.insert(make_pair(id, new Something()));
    

    Auf das Datum wird dann öfters lesend und schreibend zugegriffen. Natürlich möchte man das Datum auch löschen können. Dazu tue ich folgendes:

    cout << "Node time: " << somethingIterator->second->getTimeOfDay() << endl;
    delete somethingIterator->second;
    somethingTree.erase(id);
    somethingFound = stFasade::findSomething(id);
    if (true == somethingFound){
    	cout << "Deleted node is still present :-o" << endl;
    	progFinish(0);
    }
    

    Das kann bis zu 30.000 mal gut gehen, dann geht das aber entweder mit der folgenden Meldung schief:

    delete somethingIterator->second;
    

    Oder ich sehe die Meldung, das der gerade gelöschte Knoten noch existiert. Die ausgegebene Knotenzeit sehe ich immer, auch wenn das Programm in der darauf folgenden Zeile abstürzt. Der Knoten existiert also, und kann ausgelesen werden.
    Ich habe der erase() Funktion auch schon den iterator übergeben, daran liegt es auch nicht.
    Weiß jemand warum mir mein Programm trotzdem abstürzt?

    Grüße M. Incani



  • Kleiner Nachtrag von mir selbst:

    Das Programm scheitert natürlich mit der folgenden Meldung:

    free(): invalid pointer

    Und nicht wie versehentlich angegeben mit:

    delete somethingIterator->second;
    

    Grüße M. Incani



  • Kommt die Fehlermeldung wirklich von der Zeile

    delete somethingIterator->second;
    

    ?

    Möglicherweise wird an anderer Stelle versucht das Objekt ebenfalls zu löschen?
    Versuch mal ein
    somethingIterator->second = 0;
    einzufügen. (direkt nach dem delete somethingIterator->second; )

    Dann sollte kein Fehler mehr kommen, wenn ein zweites mal versucht wird das Objekt freizugeben.

    Coolcat



  • Hallo Zusammen,

    leider hat der letzte Beitrag keine Besserung gebracht. Ich mache nun folgendes, wobei somethingTree der Container vom Typ map ist:

    if (false == somethingTree.empty()){
    	if (somethingIterator->first == id){
    		Something *s = somethingIterator->second;
    		somethingIterator->second = NULL;
    		somethingTree.erase(id);
    		somethingIterator = somethingTree.begin();
    		if (NULL != s){
    			delete s;
    		}
    	}
    }
    if (true == somethingTree.find(id)){
    	cout << "Deleted node is still present :-o" << endl;
    	progFinish(0);
    }
    

    Und trotzdem bekomme ich die gleichen Effekte, und zwar
    free(): invalid pointer

    oder

    nach dem Löschen finde ich something in der map wieder.

    Danke schon mal an jeden, der mir einen Tipp gibt.

    Grüße Max



  • Erstmal könntest du versuchen, statt der id deinen Iterator aus der Map zu werfen.

    Zweitens gibt map::find() kein true/false zurück, sondern die Position des gefundenen Elements, als muß die Kontrollfrage lauten:

    if(somethingTree.find(id)!=somethingTree.end())
      ...
    

    Und drittens solltest du mal nachsehen, ob du deine map eventuell kopiert und in dieser Kopie Zeiger verbogen hast.



  • Hallo CStoll,

    sorry für den irreführenden Code. Natürlich gibt find() einen Iterator zurück. Wenn ich in der erase() Funktion den Iterator übergebe, passiert etwas ähnliches, nur mit einer anderen Meldung, die lautet jetzt nämlich:

    double free or corruption (!prev)

    Ich kann aber direkt vor dem Löschen auf das something zugreifen, so wie ich es in einem früheren Beitrag schonmal gezeigt hatte. something ist also direkt vor dem Löschen noch da.

    Und ich kopiere die Map nicht und verbiege auch keine Zeiger. Es wandern Zeiger auf Etwas in die Map, die bis aufs Löschen nicht mehr manipuliert werden. Ich manipuliere und lese Attribute (Werte, keine Zeiger) von Etwas und lösche Etwas. Das ist alles.

    Grüße Max



  • Hallo Zusammen,

    für alle, die an der Lösung interessiert sind. CStoll hat mich darauf gebracht, er schreibt in einem anderen Zusammenhang, ich soll

    somethingTree.find(id)!=somethingTree.end()
    

    schreiben. Wenn ich nach Elementen suche, mache ich folgendes:

    somethingIterator->first == id
    

    Und das war das Problem. Ich weiß nun zwar nicht, warum es problematisch ist, den Key direkt zu vergleichen, aber wenn ich den Vorschlag von CStoll benutze, sind alle Probleme wie weggeblasen. Vielleicht kann mir jemand erklären, warum meine Variante schief geht.

    Grüße Max



  • Wenn die Methode etwas gefunden hat, zeigt sie in deine map hinein. Das Problem dürfte sein: Wenn die Methode nichts gefunden hat, liefert sie einen Iterator auf das Ende der map (somethingTree.end()) - und den darfst du nicht dereferenzieren, weil er auf kein gültiges Map-Element zeigt (sowas nennt sich "undefined behaviour" - du kannst nicht voraussagen, was somethingTree.end()->first und ähnliche Ausdrücke zurückgeben).


Anmelden zum Antworten