Speicher freigeben... free() nach malloc führt zu HEAP CORRUPTION


  • Mod

    Nicht new und delete. Dadurch hast du doch nichts gewonnen! vector&Co. sind gemeint. Die machen nicht nur automatisch alles richtig bei der Speicherverwaltung, die kommen sogar mit einem eingebauten Debugmodus mit dem du simpelst solche Probleme finden kannst, wie wo du über deine Arraygrenzen hinaus schreibst.

    Es handelt sich um ein wissenschaftliches Program, weshalb ich aus Performancegründen tatsächlich auf <vector> verzichten möchte.

    Dann wissenschaftle doch mal, was schneller ist. malloc oder vector. Du wirst überrascht sein.



  • @SeppJ Das C-Array ist schneller - ich durchlaufe das ja nicht einfach
    nur von oben nach unten sondern muss mehrfach auf spezifische
    Zeilen zugreifen.

    Wenn ich vor Zeile 16 folgendes einfüge:

    	std::cout << Linebuffer[0] << std::endl;
    	free(Linebuffer[0]);
    

    fliegt der Fehler auch erst beim free() - es gibt also kein "übers Array hinaus iterieren".

    Und das mit dem "wissenschaftlich" sollte nicht arrogant klingen - es geht einfach um NumberCrunching - riesige Sparse-Matrizen (>10 000 000 Zeilen) einlesen und schnell lösen. Ich arbeite dabei (zw. Zeile 15 und 16 - das habe ich alles auskommentiert) durchaus mit Zeigerarithmetik etc.


  • Mod

    @CJens sagte in Speicher freigeben... free() nach malloc führt zu HEAP CORRUPTION:

    @SeppJ Das C-Array ist schneller - ich durchlaufe das ja nicht einfach
    nur von oben nach unten sondern muss mehrfach auf spezifische
    Zeilen zugreifen.

    Das hast du in wenigen Minuten getestet? Glaube ich nicht. Du plapperst nur irgendwelchen Unsinn nach, anstatt selber zu denken.

    Um es klarer zu sagen: Du hast ganz offensichtlich nicht getestet. Denn nicht nur hattest du keine Zeit, sondern du hast auch ein Ergebnis, das nicht richtig sein kann. Was denkst du denn, was ein vector ist? Wie soll der magisch langsamer sein als malloc, wenn er doch malloc unter einem anderen Namen ist?

    Ich seh' schon, dass du wissenschaftliches Rechnen machst. Als ich an der Uni war, haben wir jedoch nicht nach irgendwelchen vorsintflutlichen Mythen programmiert, sondern modernst Mittel benutzt und stets unsere Annahmen in der Praxis geprüft. Schade, dass das wohl nicht an allen Hochschulen so ist. Zumal dieser spezielle Fall hier eine ziemlich elementare Sache ist. Du machst dir einfach unnötig das Leben schwer für nichts. Hinter dem vector steht letztlich ein malloc, bloß bekommst du die ganze Sicherheit geschenkt, weil der passende Code zum Anlegen und Freigeben, den du sonst selber schreiben musst, automatisch (und korrekt) erzeugt wird. Es gibt absolut überhaupt keinen Grund jemals malloc oder new in C++ zu nutzen (außer du schreibst dir deinen eigenen vector).



  • @CJens ich sehe kein malloc in einer Schleife.
    Warum dann free?



  • Ich bin kein junger Student - schön wärs 😉 - und ich werde mich da nicht mit Dir streiten. An dem Programm sitze ich seit 2012. Das kannst Du über meine Kommentare ohne Weiteres nachvollziehen. Ich schreibe diese Methode nun zum fünften Mal, weil ich mal wieder so viele Änderungen habe, dass ich sie neu schreiben möchte. Ich habe die Klasse <vector> durchaus getestet und nutze sie auch für kleinere Arrays, welche ich nicht parallel durchlaufen muss. Ich habe es in dem speziellen Fall nicht getestet - aber ab einer gewissen Arraygröße mache ich es - aus Erfahrung- selbst.

    Am Ende geht es mir - das muss ich auch dazu sagen - darum, eine riesige Dateistruktur CMesh zu übergeben, welche ich dann via Microsoft.Runtime.Interopservice in ein C# Programm einbeziehe. Da ist es durchaus vom Vorteil, wenn man ein rohes Array übergibt - oder ich bin einfach kein guter Marshaller... Ich möchte keine externen C++ Klassen in meiner Datenstruktur. Ich nutze durchaus std::unorderd_map und andere Container aber nur zur internen Datenverarbeitung.



  • @DirkB [SOLVED] - manchmal sieht man den Wald vor lauter Bäumen nicht und reagiert auf Gewohnheiten 😃



  • Umso schlimmer...



  • @Mechanics Wenn ich pragrammiere, sollte ich beim Tabak bleiben 🤩



  • @CJens
    sizeof(char) ist immer 1
    Das Zeichen für Zeilenvorschub/ende ist i.A. '\n' (hat bei ASCII den Wert 10)
    wenn die letzte Zeile kein \n enthält, gibt es falsche Werte



  • @CJens sagte in Speicher freigeben... free() nach malloc führt zu HEAP CORRUPTION:

    throw new std::exception("ERROR\nUnable to allocate memory for buffer line length array!");}

    Seit wann wirft man Exceptions mit new? (C++ ist nicht Java)



  • @CJens sagte in Speicher freigeben... free() nach malloc führt zu HEAP CORRUPTION:

    im weiteren Verlauf des Programms brauche ich auch realloc - dafür kenne ich keine Alternative außer <vector>.

    std::vector macht kein realloc. Du könntest aber folly::fbvector nehmen, wenn du einen vector haben willst, der realloc'en kann. Wäre auf jeden Fall besser als das Rumgeflicke hier.

    Außerdem tun einige Funktionen nicht, was der Name verspricht. FileExists überprüft NICHT, ob eine Datei existiert, sondern ob eine Datei geöffnet werden kann. Das ist was anderes. Außerdem könntest du das auf std::ifstream f(filename); return (bool)f; verkürzen. Ansonsten: boost::filesystem::exists (oder std:: ab C++17) - und für GetFileSize auch. Warum selber schreiben?

    Spricht eigentlich irgendwas dagegen, die Datei gleich zeilenweise einzulesen? Du hast ja bereits einen guten Guess für die Anzahl der Zeilen, also einfach ein vector.reserve und dann die Zeilen einfach einlesen?



  • @CJens
    Ich hab mich nicht darauf bezogen, dass du einen Fehler gemacht hast, sondern darauf, dass du ein erfahrener Programmierer bist und immer noch so programmierst/denkst. Das ist, hmm, sehr suboptimal. Es gibt absolut keinen Grund für das Gefrickel mit malloc. Und deine "Erfahrungen" zeigen nur, dass du falsch getestet hast oder nicht genau verstanden hattest, was passiert oder was das Problem ist. Mit Optimierungen gebaut, hat ein std::vector überhaupt keinen Overhead im Vergleich zu einem C Array. Da ist nicht viel dahinter, das kannst du ganz einfach in Assembler verifizieren.
    Dass du die Daten an .NET übergeben musst, ist nun mal gar kein Argument. vector.data gibt dir einen Zeiger auf die Daten zurück, was exakt dem C Array entspricht.
    Außedem könnte man sich mit C++ auch unterschiedliche andere Datenstrukturen und Konzepte anschauen (allein schon, weil man schöner kapseln kann), und das ganze Problem vielleicht deutlich eleganter lösen.



  • Dieser Beitrag wurde gelöscht!