(Verständnis)Probleme mit Zuweisungsoperator überladen
-
Hallo zusammen ...
Folgendes Problem: Da ich demnächst öfter mit (TXT)Bildern hantieren muss, wollte ich mir eine kleine Klasse schreiben, die mir das Laden, Speichern und Verarbeiten erleichtert.
Es soll zum Beispiel auch möglich sein die Bildwerte verschiedener Bilder zu addieren oder auch den einen Bild die Werte eines anderen zuzuweisen, es also zu überschreiben.Aus diesem Grund wollte ich den Zuweisungsoperator überladen. Aber anscheinend kommt es da zu Problemen die zum Absturz des Programms führen ("Unbehandelte Ausnahme...")
Hier erstmal der grobe Quellcode des Programms in der main.cpp. dataIn und dataBuffer sind jeweils vom Typ int**.
... Bild.LoadTXTImg(name2,640,480); dataIn=Bild.GetDataPtr(); if (Bild.CheckValid()) { Buffer=Bild; dataBuffer=Buffer.GetDataPtr(); } else cout << "Bild " << name2 << " nicht gefunden!" << endl; Bild.Delete(); Buffer.SaveTXTImg(name3); Buffer.Delete(); ...Der Absturz kommt in "Buffer.SaveTXTImg(name3);". Diese Funktion sieht wie folgt aus:
void Image::SaveTXTImg(char C[]) { cout << "SaveTXTImg..." << endl; ofstream file; int i=0, j=0; file.open(C); if (file.good() && valid) { for (j=0;j<size_y;j++) { for (i=0;i<size_x;i++) { file << data[i][j] << "\t"; } file << endl; } } else { cout << "Datei konnte nicht geschrieben werden..." << endl; } file.close(); }Zum Absturz kommt es, da in den data[i][j] dann anscheinend nur noch Müll steht (zB -17891602).
Das lustige ist eben, dass wenn ich in der main.cpp die Zeile "Bild.Delete();" weglasse, bzw. nach den Speichervorgang setze kein Problem habe.Delete() sieht dabei wie folgt aus:
void Image::Delete() { cout << "Delete..." << endl; int i; if (valid) { for (i=0;i<size_x;i++) { free(this->data[i]); } free(this->data); this->data=NULL; this->valid = false; } }Es scheint also so, als ob mit "Buffer = Bild;" irgendwas schief läuft und die Daten dann doch nicht mehr vorhanden sind!
Hier mein Zuweisungsoperator:
Image &Image::operator=(const Image &A) { int i=0; cout << "Operator=..." << endl; this->valid=A.valid; this->size_x=A.size_x; this->size_y=A.size_y; if (A.data!=NULL) { this->data = (int**) malloc (sizeof(int*)*size_x); for (i=0;i<size_x;i++) data[i]=(int*)malloc(sizeof(int)*size_y); memcpy(this->data,A.data,sizeof(int*)*size_x*size_y); } else data=NULL; return *this; }Aber ich kopiere mit memcpy doch die Daten aus "Bild" in einen neuen Speicherbereich für "Buffer", oder?
Ich hoffe ich konnte mein Problem verständlich machen...
Ich würde mich über euere Hilfe sehr freuen!

-
ob das so mit memcpy funktioniert
, glaube mal nicht, weil die Zeiger ja irgendwo hinzeigen
Ich würde jede y-Zeile extra kopieren.
also:memcpy(this->data[i],A.data[i],size_y*sizeof(int));
-
Warum um alles in der Welt benutzt du in einem C++-Programm malloc und free?
Dieses Codestück ist unabhängig davon falsch:
for (i=0;i<size_x;i++) data[i]=(int*)malloc(sizeof(int)*size_y); memcpy(this->data,A.data,sizeof(int*)*size_x*size_y);Du legst size_x mal sizeof(int)*size_y große Blöcke im Speicher an, und erwartest das sie alle hintereinander liegen, wenn du den Inhalt kopierst. Das funktioniert nicht.
Lars
-
Ich bin mir sicher, mit einer etwas abstrakteren Herangehensweise könntest du viele Probleme beseitigen und hättest dazu noch weniger Code. Warum
malloc()undfree(), wenn wir in C++std::vector(oder andere Containerklassen) haben? Wahrscheinlich müsstest du nicht einmal den Zuweisungsoperator selbst überladen und hättest Dinge wie Exceptionsicherheit, garantierte Speicherfreigabe und hohe Performance gratis, während du momentan mit Memory Leaks zu kämpfen hast.Ich stelle mir das so vor:
class Image { public: // Erzeugt leeres Bild mit Abmessungen 0*0 Pixel Image(); // Lädt Bild aus Datei (ruft LoadFromFile() auf) Image(const std::string& filename); // Erzeugt leeres Bild mit Breite und Höhe Image(unsigned int width, unsigned int height); // Lädt Bild aus Datei void LoadFromFile(const std::string& filename); // Speichert Bild in Datei void SaveToFile(const std::string& filename); // Gibt Bildbreite zurück unsigned int GetWidth() const; // Gibt Bildhöhe zurück unsigned int GetHeight() const; // Dinge wie delete oder operator= sind unnötig ... private: std::vector<int> data; // 2D- auf 1D-Array abbilden unsigned int myWidth; };Wenn du keine Exceptions verwenden möchtest, kannst du auch
bool-Rückgaben verwenden (dann musst du eben auf Konstruktoren, die potentiell fehlschlagen, verzichten). Aber bitte nicht C-Konstrukte wieDelete(), bei deren Vergessen undefiniertes Verhalten oder Memory Leaks entstehen.
-
Ok...
Also vielen Dank erstmal für euere Hilfe!
malloc() und free() verwende ich einfach nur, weil ich es sozusagen nicht besser weiß
Ich brauchte ein Array mit dynamischer Größe und hab das mit rudimentären C-Kenntnissen so zusammen geschustert.Zu meiner Schande muss ich gestehen, dass ich bis jetzt noch nicht wirkicht mit std::vector zu tun hatte

Werde das aber schleunigst nachholen...Ich glaube also, dass sich das Problem geklärt hätte.
Danke
-
In meinem Post gibt es einen Link, dort findest du eine gute Einführung in die STL.

Und zur Dokumentation/Referenz der Standardbibliothek kannst du www.cplusplus.com verwenden.