Wieso kommt da eine HEAP CORRUPTION DETECTED



  • Hallo Leute,

    ich brauch mal ein bisschen Hintergrundwissen. Also folgendes: Ich habe eine Klasse erstellt, die einen bestimmten Dateityp lädt (ein Bild). Da im Bild die Länge / Breite geschrieben steht, lese ich erst diese Daten aus und dann die Bildwerte. Da ich ja von anfang an nicht weiß, wie groß die Länge bzw. Höhe ist, muss ich dynamisch Speicherplatz allokieren (malloc und so).

    Im Grund wird das malloc im Constructor gemacht. Nun hab ich mir gedacht, ich mach im Destructor auch ein free-Befehl rein. Doch VS2008 sagt mir, ich hab eine HEAP CORRUPTION. Google an, Suche was los ist. In diesem Forum schreibt einer, dass es sein kann, dass ich ein free-Befehl zu viel hab.

    Ok, hab also den free-Befehl wieder rausgenommen und kein Fehler mehr. Jetzt die Frage: Warum? Ich mein, wenn ich schon ein malloc-Befehl mache, dann muss ich doch auch ein free machen, oder etwa nicht?

    Kann man mit C++ irgendwie sicher stellen, dass der Speicherplatz am Schluss wieder frei ist?



  • Du schreibst irgendwo über Arraygrenzen drüber oder sonst auf Speicher, der dir nicht gehört. Dabei zerschießt du unter anderem gewisse Verwaltungsinformationen für die Speicherverwaltung, was dann beim free auffällt.

    BTW malloc/free gehören nach C und nicht nach C++.



  • Hmm...ok. Jetzt hab ich folgendes gemacht: Da mein Bild Breite * Höhe breit ist, hab ich nun folgendes geschrieben:

    m_Values = (int *)malloc(sizeof(int) * (width * height + 1));
    

    Wenn ich nun free aufrufe, kommt kein Fehler. Scheint wohl auszureichen.

    BTW malloc/free gehören nach C und nicht nach C++.

    Oh, das wusste ich nicht. Na dann kann man den Thread ja verschieben ...



  • starki schrieb:

    Hmm...ok. Jetzt hab ich folgendes gemacht: Da mein Bild Breite * Höhe breit ist, hab ich nun folgendes geschrieben:

    m_Values = (int *)malloc(sizeof(int) * (width * height + 1));
    

    Wenn ich nun free aufrufe, kommt kein Fehler. Scheint wohl auszureichen.

    Du solltest besser den Fehler suchen. Vielleicht benutzt du EOF falsch.

    BTW malloc/free gehören nach C und nicht nach C++.

    Oh, das wusste ich nicht. Na dann kann man den Thread ja verschieben ...

    Programmierst du denn in C? Ich meinte eigentlich, dass man in C++ dynamischen Speicher anders anfordert.



  • Ne eigentlich benutze ich C++. Wie fordert man dynamischen Speicher in C++ an?

    Also meine Lösung scheint die richtige zu sein. Ich hab ja hier eine Datei, an der ich das ausprobieren kann. Dieses Bild hat 350 * 450 Pixel = 1575000 Pixel.

    Wenn ich Speicher allokiere (so wie ich das in der Zeile mache), dann allokiere ich 1575000 * sizeof(int) Bytes.

    D.h. wir können annehmen, dass ich ein Array mit 1575000 Elementen habe. Als ich mal reindebuggt habe, kam heraus, dass das letzte geschriebene Element das Element 1575000 war, aber es hätte ja 157499 sein dürfen. Scheint also schon richtig zu sein, wenn ich da um eins erhöhe... (also ich sehe da keinen Fehler):

    // Speicher allokieren.
    m_Values = (int *)malloc(sizeof(int) * (m_width * m_height + 1));
    int write_pos = 0;
    char c;
    
    // ... 
    
    while (!ppm.eof())
    {
    	// Little Endian
    	int val = 0;
    	ppm.get(c);
    	val = 256 * 256 * c;
    	ppm.get(c);
    	val += 256 * c;
    	ppm.get(c);
    	val += c;
    	m_Values[write_pos] = val;
    	write_pos++;
    }
    

    Dass ich hier dreimal ein get mache, muss so sein, da ich von jedem Pixel den Rot-, Grün- und Blau-Wert lade und zusammenrechne.



  • Du benutzt EOF falsch!

    C malloc/free => C++ new/delete bzw new[]/delete[]

    besser: std::vector

    Am Besten: C++ lernen



  • starki schrieb:

    Ne eigentlich benutze ich C++. Wie fordert man dynamischen Speicher in C++ an?

    new/delete bzw. std::vector.

    Also meine Lösung scheint die richtige zu sein. Ich hab ja hier eine Datei, an der ich das ausprobieren kann. Dieses Bild hat 350 * 450 Pixel = 1575000 Pixel.

    Wenn ich Speicher allokiere (so wie ich das in der Zeile mache), dann allokiere ich 1575000 * sizeof(int) Bytes.

    Und es kommt dir nicht komisch vor, dass das Bild da nicht reinpasst?

    while (!ppm.eof())
    {
    	// Little Endian
    	int val = 0;
    	ppm.get(c);
    	val = 256 * 256 * c;
    	ppm.get(c);
    	val += 256 * c;
    	ppm.get(c);
    	val += c;
    	m_Values[write_pos] = val;
    	write_pos++;
    }
    

    Wie gesagt, EOF falsch benutzt. ppm.eof() wird erst dann true, wenn du einmal versucht hast, über das Dateiende hinweg zu lesen, also in deinem Fall, wenn ein ppm.get() fehlgeschlagen ist. Du fängst das aber nicht ab, so dass du am Ende genau einen Wert zuviel verarbeitest. (Sehr typischer Anfängerfehler übrigens, deshalb hab ich das gleich vermutet.)

    Das Muster sollte eher ungefähr so aussehen:

    while (true) {
      if (!ppm.get(c))
        break;
      ...
    }
    


  • @Bashar: Danke für deine Rückmeldungen 🙂 . Habe jetzt wieder was neues gelernt 🙂 Hab nun mein Code angepasst und es sollte nun klappen. Das mit dem dem EOF-Fehler war mir nicht bekannt ...


Log in to reply