Probleme mit new und delete



  • Hallo!

    Habe folgendes Problem:

    *** glibc detected *** ./dosome: free(): invalid next size (normal): 0x09b8e7c8 ***
    

    Der Fehler tritt auf, wenn ich ein Array freigebe. Das Array wurde mit

    int* myArray = new int[mySize];
    

    angefordert und mittels

    delete[] myArray;
    

    freigegeben. Also genau so, wie es sich gehört. Bei der delete[]-Anweisung crasht das Programm mit o.g. Fehlermeldung.

    Jemand eine Idee, was hier schief läuft?



  • Du hast dir wahrscheinlich schon vorher etwas zerschossen.
    Evtl mal ein Minimalbeispiel?



  • Minimalbeispiel ist sehr schwierig, da ich nicht weiß, ab wo es kaputt geht. Mehr Code zeigen ist auch keine sinnvolle Option, denn es handelt sich mittlerweile um > 10k LoC.

    Habe nun auch mal Valgrind laufen lassen. Allerdings fällt es mir schwer, die Ausgabe zu interpretieren.

    Valgrind gibt mir folgendes aus:

    ==23746== Invalid write of size 4
    ==23746==    at 0x8050587: MyClass::DoSomething() (MyClass.cpp:21)
    ==23746==    by 0x8051387: main (main.cpp:xx)
    ==23746==  Address 0x60f63ec is 0 bytes after a block of size 12,388 alloc'd
    ==23746==    at 0x4005E1E: operator new[](unsigned) (vg_replace_malloc.c:268)
    ==23746==    by 0x8051387: main (main.cpp:xx)
    

    Ich habe eine Klasse MyClass. Die sieht (stark vereinfacht) so aus:

    class MyClass {
      public:
    	MyClass();
    	~MyClass();
    	DoSomething();
    
    	float* myArray;
    	int mySize;
    
    }
    
    MyClass::MyClass() : mySize(100) {
    	myArray = new float[mySize];
    }
    
    MyClass::~MyClass() {
    	delete[] myArray;
    }
    
    MyClass::DoSomething() {
    	myArray[23] = 42;
    }
    

    Valgrind meckert also nun die Zeile 20 an. Warum? Das Array ist mit 100 Plätzen allokiert. Also sollte doch ein Schreibvorgang auf Zelle 23 funktionieren.
    Wie ist die Aussage "Address 0x60f63ec is 0 bytes after a block of size 12,388 alloc'd" zu verstehen? Zeigt mir das schon einen Fehler?
    Aber warum haben wir hier einen Fehler?

    Wenn ich das Programm durch Valgrind laufen lasse, crasht es übrigens nicht.

    Habe new[]/delete[] auch mal durch malloc/free ersetzt. Keine Änderung.

    Wo könnte der Fehler liegen und wie kann ich dahin kommen?



  • glibc detector schrieb:

    Valgrind meckert also nun die Zeile 20 an.

    Natürlich Zeile 21: myArray[23] = 42;
    Bin mit den Zeilen durcheinander gekommen.



  • Rückgabewert default auf int, aber es wird nichts zurückgegeben?!



  • lagalopex schrieb:

    Rückgabewert default auf int, aber es wird nichts zurückgegeben?!

    Welchen Rückgabewert meinst du? Verstehe nicht ganz, worauf du hinaus willst...



  • Du hast für DoSomething(); keinen Rückgabewert angegeben. Daher wird ein int angenommen. Nun gibst du aber keinen int zurück, was dir den Speicher durcheinander bringt. An sich müsste jeder gescheiter Compiler zumindest ne Warnung dazu ausgeben.



  • Achso. Das ist nur im Forum so. Im Originalquelltext gibt es dort natürlich einen Rückgabewert.
    Tut mir leid, den habe ich vergessen.

    Neuer Fehler, wenn ich vor dem delete[] in mein Array schreiben will:

    *** glibc detected *** ./dosome: malloc(): memory corruption: 0x08ee6510 ***
    

    Auch hier ist es wieder so, dass es mit Valgrind funktioniert.



  • Mischen von malloc/free und new/delete ist nicht gut.
    Du programmierst C++ also nimm new und delete.

    Ansonsten kann man dir kaum helfen, so ohne Code. Höchstens im Umgang mit valgrind...



  • Aus dem Code geht leider der Fehler nicht hervor. Daher poste am besten ein minimales aber vollständiges Beispiel, bei dem es zu dem Problem kommt.



  • Ja, ich weiß, ohne Code ist es schwer. Aber etwas Valgrind-Hilfe wäre schon fein, z.B. wie o.g. Fehlermeldung zu interpretieren ist.

    In meinem Code nutze ich nur new/delete bzw. new[]/delete[]. Allerdings nutze ich Legacycode, der eine ganz fiese Mischung aus C und C++ ist. Da wird dann aber nur malloc/free genutzt.
    Die Daten, die mir der Legacycode gibt, packe ich weder mit delete noch mit free an, das macht der alles selbst. Ich räume nur meinen Mist auf, mit dem passenden Operator.

    Oder ist mit Mischen genau das gemeint? Ist Mischen auch schon, wenn ich einzelne Speicherbereiche immer mit dem gültigen malloc/free bzw. new/delete bearbeite, aber innerhalb des ganzen Programmes wild wechsele? Also wenn new/delete, dann nirgendwo im Code malloc/free?



  • rüdiger schrieb:

    Aus dem Code geht leider der Fehler nicht hervor. Daher poste am besten ein minimales aber vollständiges Beispiel, bei dem es zu dem Problem kommt.

    Ja, das versuche ich gerade. Aber den Fehler nachzustellen ist nicht einfach.



  • Ok, Problem gelöst, Valgrind sei Dank.
    Der Legacycode legt mehrere Arrays an. Eines davon nicht von 0 bis n-1, sondern von 1 bis n. Ich weiß nicht, warum man bei 1 anfängt, ist auch unerheblich.

    Der Punkt war der, dass ich natürlich über die Grenze hinausgeschrieben habe.
    (Toll nur, dass mir das kein einziges Programm sagt. Mit MSVC geht sowas besser... egal)

    Aber mit Valgrind konnte ich die Stelle finden und nun meine Leaks behandeln. Die aus dem Legacycode leider nicht, aber den darf ich auch nicht ändern...

    Aber die o.g. Frage zum gleichzeitigen Verwenden von malloc/free und new/delete in einem Programm, wobei die einzelnen Allokationen und das Freigeben durchaus gültig mit der richtigen Kombination geschehen, interessiert mich trotzdem noch.
    Kann da jemand was zu sagen?


Log in to reply