C++ HEAP Corruption detected

Puepue

Komplett-PC-Aufrüster(in)
Hallo zusammen,
habe ein Problem bei einem Schulprojekt..
Ich habe eine Klasse geschrieben, die einen Poitner mit einem Wort enthält (bspw. "Hallo") - wenn ich den angeforderten Speicher im Destructor mit delete[] freigeben will, diesen doofen Heap Corruption error (kommt ja eigentlich nur, wenn man nicht-allokierten Speicher freigeben will, oder?
Screenshot + Projekt anbei

Dankööö
 
nee, das kann auch passieren, wenn du wo drüber pinselst. Ich suche gerade mal im Code nach möglichen Problemstellen...
 
Super, danke!
FYI: Der Fehler tritt auch auf, wenn ich das Programm direkt nach der Satzeingabe mit Esc beende - also keine der Menüpunkte ausführe
 
Also erstmal hab ich nen Speicherleck gefunden (in der memManager-Funktion):

Code:
char * oldString = this->pString;
Du merkst dir da zwar den alten String zum Kopieren, gibst den allozierten Speicher aber nach der Kopiererei nicht frei.

Mein erster Verdacht:
Code:
for(i=0;i<((size * zuKopierendeBloecke) + this->getTextlaenge());i++)
        {
            /*cout << "size: " << size << endl;
            cout << "zuKopierendeBloecke: " << zuKopierendeBloecke << endl;
            cout << "this->blockgroesse: " << this->blockgroesse << endl;
            cout << "vorhandeneBloecke: " << vorhandeneBloecke << endl;
            cout << "this->getTextlaenge(): " << this->getTextlaenge() << endl;
            cout << "i: " << i << endl;*/
            pString[i] = oldString[i]; // <- oldString ist kleiner als pString, Überlauf?
        }

Der erste Aufruf der memMgmt-Funktion liefert bei mir auch hier 0 chars (Blockgröße 8)!
Code:
this->pString = new char[(size * zuKopierendeBloecke) + this->getTextlaenge()]; // size = 1 * zuKopierendeBlöcke = 0 + Textlen = 0 ergibt 0!
 
Hmm diese doofe Funktion.. war an der Stelle schon x-mal.. das schaue ich mir mal an... vermutlich reicht da ja eine Abfrage, dass da mind. 1 raus kommen muss, kann das sein?
 
So, habe es glaube ich gefunden:
Code:
// Ans Ende eine binaere Null setzen
        pString[i+1] = '\0';
Im ersten Durchgang wird bei mir ein Array der Größe 0 erzeugt (Siehe vorherigen Post), hier wird aber mindestens an Position 1 geschrieben => außerhalb des allozierten Bereichs.
 
Hmmm das macht natürlich Sinn, ich bin mir nur nicht sicher, wie ich das umgehen soll - wenn ich das hier mache (habe jetzt immer ein + 1 ans ende gehangen), stürzt das Programm in der 1. For-Schleife ab ( denke mal, weil es dann kein oldString gibt, weil oldString ist ja leer..
Code:
char * oldString = this->pString; //merken
        cout << "oldString gemerkt" << endl;

        int tmpGroesse = (size * zuKopierendeBloecke) + this->getTextlaenge() + 1;

        //this->pString = new char[this->getTextlaenge() + size + 1];
        
        this->pString = new char[tmpGroesse];

        //cout << "Speichert in Groesse " << size * this->blockgroesse << " allokiert" << endl; 
        cout << "Speicher in Groesse " << tmpGroesse << " allokiert" << endl; 

        
        cout << "Durlaufe For-Schleife " << tmpGroesse << " mal ..";
        int i = 0;
        for(i = 0; i < tmpGroesse; i++) {
            /*cout << "size: " << size << endl;
            cout << "zuKopierendeBloecke: " << zuKopierendeBloecke << endl;
            cout << "this->blockgroesse: " << this->blockgroesse << endl;
            cout << "vorhandeneBloecke: " << vorhandeneBloecke << endl;
            cout << "this->getTextlaenge(): " << this->getTextlaenge() << endl;
            cout << "i: " << i << endl;*/
            pString[i] = oldString[i];
        }
        cout << "..done" << endl;

        // Ans Ende eine binaere Null setzen
        cout << ".. i: " << i << endl;
        pString[i+1] = '\0';
 
Wenn ich das +1 weglasse, und einfach so abfrage:
Code:
if (i > 0) {
            pString[i+1] = '\0';
        }

stürzt das Programm zwar nicht ab, aber es kommt wieder Heap corruption dabei raus
 
Länge von pString != Länge von ostring in der Schleife. Du läufst vermutlich zu weit. Du darfst nur Länge(ostring) elemente kopieren, also die Länge des alten Arrays kennen/herausfinden.
 
hmm.. ist vermutlich einfach nur schon zu spät .. aber wie mach ich das am besten bei
Code:
char * oldString = this->pString; //merken
int strlenOld = strlen(oldString);

schmiert das Programm einfach so ab und bei dem hier auch:
Code:
int strlenOld = strlen(this->pString);
char * oldString = this->pString; //merken
 
ich habe auch die Vermutung, dass du pString im Konstruktor nicht auf NULL initialisiert hast bzw. in der memManager-Funktion nicht darauf prüfst. Ich bin ja mit dem Debugger im Einzelschrittmodus mal durch die Funktion gegangen und der Zeiger war nicht NULL - obwohl noch keine Daten drinnen stehen können -> strlen greift auf Speicher zu, der deinem Programm nicht gehört.
 
Ich versuche jetzt seid einer guten halben Stunden deinen Code zu verstehen und komme da einfach nicht weiter. :what:

Du erzeugst am anfang einen leer String, also quasi nur eine abschließende 0 und hängst in dieser "memManager" Funktion jedes mal eine weitere 0 ans Ende .... warum?:huh:

Edit:
Jetzt verstehe ich das! Allllsssssoooooo, dein Problem ensteht, wie Bingo schon sagte, in der Zeile in der du das Abschlußzeichen setzt. Die Lösung an dieser Stelle ist aber nicht ganz so einfach, da du leider keinerlei Code hast, der Prüft ob hier ein null Pointer vorhanden ist! Du wirst dir die gesamte memManager Funktion noch einmal vornehmen müssen. Vielleicht ist es an dieser Stelle ein guter Ansatz wenn du, in dieser Funktion auch nur das machst, was der Name vermuten liese ... nur den Speicherverwalten. ;)
 
Zuletzt bearbeitet:
Ja, in der Funktion wird vermutlich das Problem liegen. Ist das Programm eigentlich zu einer Aufgabe oder hast du dir das selbst überlegt?
 
War wohl wirklich zu spät :)
Habs jetzt alles in allem so gemacht:

Code:
// memManager
void TString::memManager (int size)
{
    if (this->getTextlaenge() < 0) {        // man weiß ja nie... 
        if (size < 0) {
            this->setTextlaenge(0);
        } 
        if (size >= 0) {
            this->setTextlaenge(size-1);
        }
    }
    int lenOld = 0;
    lenOld = this->getTextlaenge();

    int benoetigteBloecke = (size/this->blockgroesse);

    if (size % this->blockgroesse > 0) {        // Wenn Rest
        benoetigteBloecke ++;            
    }

    int vorhandeneBloecke = getBlockZahl();

    // Wenn weniger Blocke vorhanden, als benoetigt => vorhandene Bloecke, sonst benoetigte Bloecke
    int zuKopierendeBloecke = (vorhandeneBloecke < benoetigteBloecke) ? vorhandeneBloecke : benoetigteBloecke;

    if (benoetigteBloecke != vorhandeneBloecke) {
        cout << "benoetigteBloecke != vorhandeneBloecke";
        char * oldString = this->pString; //merken
        cout << "oldString gemerkt" << endl;

        int tmpGroesse = (size * zuKopierendeBloecke) + this->getTextlaenge();

        //this->pString = new char[this->getTextlaenge() + size + 1];
        
        this->pString = new char[tmpGroesse];

        //cout << "Speichert in Groesse " << size * this->blockgroesse << " allokiert" << endl; 
        cout << "Speicher in Groesse " << tmpGroesse << " allokiert" << endl; 

        cout << "Durlaufe For-Schleife " << lenOld << " mal ..";
        int i = 0;
        for(i = 0; i < lenOld; i++) {
            /*cout << "size: " << size << endl;
            cout << "zuKopierendeBloecke: " << zuKopierendeBloecke << endl;
            cout << "this->blockgroesse: " << this->blockgroesse << endl;
            cout << "vorhandeneBloecke: " << vorhandeneBloecke << endl;
            cout << "this->getTextlaenge(): " << this->getTextlaenge() << endl;
            cout << "i: " << i << endl;*/
            pString[i] = oldString[i];
        }
        cout << "..done" << endl;

        // Ans Ende eine binaere Null setzen
        cout << ".. i: " << i << endl;
        if (i > 0) {
            pString[i+1] = '\0';
        }
        

        cout << "Binaere Null gesetzt" << endl;

        /*cout << "Setze Blockzahl auf " << benoetigteBloecke << endl;
        setBlockZahl(benoetigteBloecke);*/
        cout << "Setze Blockzahl auf " << this->getBlockZahl() << " plus " << benoetigteBloecke << endl;
        setBlockZahl(this->getBlockZahl() + benoetigteBloecke);
    }

    this->setTextlaenge(this->getTextlaenge() + (size-1));

}
 
Hab aber mal ne andere Frage.. du schreibst immer alloziert .. ich bin aber der festen Überzeugung allokiert gelernt zu haben - ist das das gleiche?
 
Oh sehe gerade, dass da vor mir ein paar Posts waren (böser Cache) :)
Das Programm ist eine Schulaufgabe (würde niemals freiwillig wsowas in c++ programmieren, bin in php zuhause da erspar ich mir das :P) - dabei sind alle Funktionen vorgegeben - auch der memmanager - aber so klappt es jetzt, danke für den Tipp mit dem Merken der alten Länge :)
 
Zurück