Heap Corruption Detected... Probleme eines Anfängers
-
Hallo,
ich bin dabei das Buch Einstieg in Visual C++ 2008 durchzuarbeiten. Ich bin gerade beim Kapitel "Dynamische Speicherverwaltung" und wenn ich mein selbstgeschriebenes Übungsprogramm starte kommmt am Ende immer dieselbe Fehlermeldung: Heap Corruption Detected .......
So nun habe ich im INet und auch hier im Forum ein wenig gestöbert und bin auch auf einige Themen gestossen. Das Problem ist nur, daß diese mich meistens noch weiter verwirren...
Und mein Problem ist immer noch nicht gelöst.
Wäre nett wenn sich mal jemand des Problems annehmen könnte.
Mein Problem ist auch, daß ich nicht genau weiß wo das delete stehen muß um den Speicher wieder freizugeben. Wenn ich im Konstruktor ein new habe dann muß ich im Destruktor das delete stehen haben ?! und wenn ich in einer Methode ein new stehen habe ???Ich komme im moment nicht weiter und Hilfe wäre nett.
Mit freundlichen Grüßen
sub
Die dynintfeld.h:
#pragma once class dynintfeld { public: // Attribute int *feld; int *feld_1; int groesse; int groesse_1; // Konstruktoren dynintfeld(int g); // dynintfeld(int g, int g_1); // Destruktoren virtual ~dynintfeld(); // Methoden int getWert(int pos) const; void setWert(int w, int pos) const; void setWert(int pos) const; void add(int m);// void feldfuellen(int n); //void killen(); virtual void ausgabe() const; };Die dynintfeld.cpp:
#include "dynintfeld.h" #include<iostream> dynintfeld::dynintfeld(int g) : groesse(g) { feld = new int[groesse]; } /* dynintfeld::dynintfeld(int g, int g_1) : groesse(g), groesse_1(g_1) { int neue_groesse = g + g_1; feld = new int[neue_groesse]; }*/ int dynintfeld::getWert(int pos) const { return(feld[pos]); } void dynintfeld::setWert(int w, int pos) const { feld[pos] = w; } void dynintfeld::setWert(int pos) const { feld_1[pos] = 0; std::cout << "feld" << pos << " = " << feld_1[pos]; } void dynintfeld::add(int m) { feld_1 = new int[m]; } void dynintfeld::feldfuellen(int n) { feld_1[n] = 0; } void dynintfeld::ausgabe() const { } /* void dynintfeld::killen() { delete[](feld_1); }*/ dynintfeld::~dynintfeld() { delete[](feld); delete[](feld_1); }Die main.cpp:
#include <iostream> #include <string> #include "dynintfeld.h" using namespace std; int main () { //_CrtSetDbgFlag(_CrtSetDbgFlag(0)|_CRTDBG_CHECK_ALWAYS_DF); cout << "\nWie gross soll das Feld sein? [Zahl zwischen 1 und 10]: "; int zahl; cin >> zahl; dynintfeld dynfeld(zahl); // Objekt dynfeld erstellen dynintfeld *p = &dynfeld; // Zeiger auf die Startadresse des Objektes int wert; // Zahlenwerte für die Felder for (int i = 0; i < zahl; i++) { cout << "\nBitte geben Sie den Wert fuer das " << i+1 << ". Feld an: "; cin >> wert; dynfeld.setWert(wert, i); } for (int k = 0; k < zahl; k++) { cout << "\nFeld " << k+1 << " hat den Wert " << dynfeld.getWert(k) << endl; } int zahl_1; cout << "\nWieviele Elemente moechten Sie noch an das Feld anhaengen? "; cin >> zahl_1; cout << "\nDas ganze Feld besteht jetzt aus " << zahl_1+zahl << " Feldern\n"; if (zahl_1 != 0) // wenn die Anzahl hinzugefügter Felder größer 0 ist ... { dynfeld.add(zahl_1); // neues Feld generieren for (int i = 0; i < zahl_1+zahl; i++)// die neuen Felder mit Nullen füllen ansonsten steht da irgendein Schrott drin { dynfeld.setWert(i); } //dynfeld.killen(); for (int i = 0; i < zahl; i++) // neues Feld mit den Zahlen des alten Feldes füllen { int hilfe = dynfeld.getWert(i); dynfeld.feld_1[i] = hilfe; for (int k = zahl; k < zahl_1+zahl; k++)// die neuen Felder mit Nullen füllen ansonsten steht da irgendein Schrott drin { dynfeld.feld_1[k] = 0; } } for (int k = 0; k < zahl+zahl_1; k++) { cout << "\nFeld " << k+1 << " hat den Wert " << dynfeld.feld_1[k] << endl; } } else { for (int k = 0; k < zahl; k++) { cout << "\nFeld " << k+1 << " hat den Wert " << dynfeld.feld[k] << endl; } } cout << endl << endl; // ENDE!
-
Ich weiß nicht ob das dein Problem ist, möglich wärs:
dynintfeld::dynintfeld(int g) : groesse(g) { feld = new int[groesse]; } dynintfeld::~dynintfeld() { delete[](feld); delete[](feld_1); }Vergleich mal deinen Ctor und deinen Dtor.
Was passiert wenn ich dein dynintfeld konstruiere und sofort wieder zerstöre?
feld_1 ist nicht initialisiert und zeigt irgendwo hin, und wenn du das löscht gibt's eben eine Fehlermeldung.Schreib in deinen Ctor
feld_1 = 0;Unabhängig davon ob es dein Problem löst, musst du dieses Problem beseitigen (delete [] feld_1 macht nichts wenn feld_1 == 0 )
-
Ach ja, noch ein paar weitere Dinge:
Zuweisungsoperator und Kopierkonstruktor fehlen - die automatisch vom compiler generierten reichen nicht und verursachen einen crash sobald du sie verwendest.void dynintfeld::add(int m) { feld_1 = new int[m]; }Das ist ein memory leak. Richtig wäre:
void dynintfeld::add(int m) { delete [] feld_1; //hier gilt wieder: entweder feld_1 zeigt auf speicher den du vorher mit add reserviert hast, oder auf 0 durch den Ctor feld_1 = new int[m]; }Ähnlich solltest du auch Zuweisungs und Copy-Ctor implementieren.
-
Hallo,
danke für deine schnelle Antwort.
Mein Problem ist damit gelöst, aber da wäre ich ja im Leben nie darauf gekommen...Wieso muß denn jetzt das delete vor dem new int stehen ???
Und wieso ergibt
feld_1 = new int[m];ein memory leak ?? Im Ctor wird das doch genauso gemacht nur halt mit feld.
Und du sagtes feld_1 wird nicht initialisiert. Das habe ich nicht gemacht,weil feld ja auch nicht initialisiert wurde in den Beispielen und da funktioniert das auch.Das verwirrt mich ein wenig!!!
Ach und copy und zuweisungs -ctor habe ich nicht implementiert, weil die Übung das vorgegeben hat. Ich sollte eine Methode add implemetieren.
Grüße
sub
-
sub-elektro schrieb:
Und wieso ergibt
feld_1 = new int[m];ein memory leak ?? Im Ctor wird das doch genauso gemacht nur halt mit feld.
Im CTor ist das feld ja noch nicht initialisiert! Wenn du aber zu einem späteren Zeitpunkt einfach dein Array mit new neu anlegst, ist der alte dynamisch alloziierte Speicher nicht mehr erreichbar -> memory leak. Deshalb vorher löschen, evtl. erst alte Daten in ein temporäres Objekt swappen, falls du die noch brauchen solltest..
-
sub-elektro schrieb:
Hallo,
Wieso muß denn jetzt das delete vor dem new int stehen ???Und wieso ergibt
feld_1 = new int[m];ein memory leak ?? Im Ctor wird das doch genauso gemacht nur halt mit feld.
Der große unterschied zwischen dem ctor und einer funktion ist, der ctor wird genau einmal ausgeführt, eine Funktion kann auch mehrmals ausgeführt werden.
Wenn du zwei mal add verwendest, reservierst du das erste mal Speicher, und lässt feld_1 auf diesen Speicher zeigen. Beim zweiten mal reservierst du wieder Speicher, und lässt feld_1 auf diesen völlig anderen Speicher zeigen. (Bei weiteren malen dasselbe spielchen). Wird schließlich das Objekt zerstört, wird der zuletzt angeforderte Speicher freigegeben, der Speicher den du dir davor geholt hast bleibt aber reserviert - ein memory leak.sub-elektro schrieb:
Und du sagtes feld_1 wird nicht initialisiert. Das habe ich nicht gemacht,weil feld ja auch nicht initialisiert wurde in den Beispielen und da funktioniert das auch.
Das verwirrt mich ein wenig!!!
Das Problem ist, wenn du feld_1 (damit meine ich nicht das array oder sowas wo feld_1 hinzeigt, sondern die variable feld_1 selbst) nicht einen Wert zuweist, zeigt das irgendwohin. Nicht auf gültigen Speicher, nicht auf 0, sondern eben irgendwo. Und wenn du im Dtor dann sagst, "gib mal das frei, wo feld_1 hinzeigt", und der zeigt in irgendwelchen Speicher der ihm gar nicht gehört, dann versuchst du Speicher zu löschen der dir nie gehört hat -> heap corruption.
sub-elektro schrieb:
Ach und copy und zuweisungs -ctor habe ich nicht implementiert, weil die Übung das vorgegeben hat. Ich sollte eine Methode add implemetieren.
Grüße
sub
War nur als allgemeiner Hinweis gedacht, weil ich weiß aus eigener Erfahrung, dass wenn man dann doch einmal so eine Semantik braucht, man es eben leicht vergisst und dann - später - wieder Fehler sucht.
-
Alles klar habe ich verstanden.
Vielen Dank!
grüße
sub