Objekt wird nach beenden einer Funktion gelöscht? access violation.
-
Hallo erstmal, da ich neu in diesem Forum bin.
Zweitens weiss ich nicht ob dies ein C++ grundlagen Misverständnis ist oder ob's ein vc++/mfc spezifisches ist.
Ein bisschen von beidem schätze ich, da wenn ich eine main() hätte könnte ich ne globale variable benutzen und weg wäre das Problem, aber schaut mal selber.Also in dem Projektgeht es grob gesehen darum eine 512x512 Matrix mit jeweils 32bit Werten einzulesen, in eine .BMP zu wandeln und diese dann in einem vom User gewünschtem Pfad speichern.
In letzterem liegt mein Problem.
Es ist ein SDI-Projekt und die Klasse die wir benutzen für die Anfangsmatrix heisst _32Bit512 und wird deklariert eine Bilder.h header-datei.
class _32Bit512{ private: int *bild; public: _32Bit512(); _32Bit512(int *array); ~_32Bit512(); int lesen(int x, int y) { return bild [y*512+x]; } void schreiben(int x, int y, int wert) { bild [y*512+x] = wert; } void toBitmap(CString bmpPath); };
Soweit keine probleme. Dann habe ich in der Oberfläche einen Button über den die Matrix von der Platte einliest und anzeigt. Die Funktion heisst OnGetMatrix() und ist member der CM2BMPview klasse.
void CM2BMPView::OnGetMatrix() { ... _32Bit512 orgBild(iBuffer); // iBuffer ist die von der Platte eingelesene Matrix. staticBild = orgBild; //hier liegt mein Problem. staticBild.toBitmap("C:\\Windows\\temp\\matrix_ausdruck.bmp"); //hier funzt die Funktion. ... }
Wobei staticBild wiefolgt in der M2MBPView.h deklariert wird.
class CM2BMPView : public CFormView { ... // Attribute public: ... _32Bit512 staticBild; ... };
Nun kann ich in der OnGetMatrix() funktion staticBild uneingeschränkt nutzen. Aber es scheint sobald die Funktion durchgeführt und beendet wurde, wird das Objekt welches zu staticBild gehört gelöscht. Und das ist nicht gut, da ich in der nächsten Funktion das staticBild Objekt nochmal brauche:
void CM2BMPView::OnSaveAsBMP() { ... CString pathBitmap; pathBitmap = fdlg.GetPathName(); ... staticBild.toBitmap(pathBitmap); // hier wird staticBild nochmal benutzt }
in dieser letzten Zeile wird die _32Bit512::toBitmap(CString bmpPath) nochmal aufgerufen und in dieser Funktion wird die _32Bit512::lesen(int x, int y) mehrmals aufgerufen, und beim ersten aufruf gibts die 0xC0000005 Access Violation.
Ich habe gestern einige Stunden an dem Problem gehockt und bin keinen milimeter weitergekommen. Also ich bin noch ziemlicher Anfänger bezüglich den MFC und deshalb wusste ich auch nicht ob es sowas wie eine WinMain() in der Win32API gibt wo ich eine globale Variable _32Bit512 staticBild deklarieren könnte, auch wenn es OO-technisch unsauber wäre.
Die OO-typische Lösung hierzu hätte ich aber genauso gerne wie irgendeine andere Lösung. Denn in knapp zwei Wochen ist Abgabetermin für's Projekt ist.Danke das ihr euch die Zeit genommen habt das alles durch zu lesen aber besser zuviele Informationen als zu wenige. Falls ihr noch mehr braucht fragt
gruss, plain
-
Hi,
offensichtlich weist dein operator= in dieser Zeile:staticBild = orgBild; //hier liegt mein Problem.
deinem int* Attribut bild nur den Wert des bild Attributs von orgBild zu.
Es zeigen also beide int Pointer auf den gleichen Speicherbereich.
Da orgBild aber nur lokal ist denke ich dass der Destruktor am Ende von OnGetMatrix den Speicher hinter dem Zeiger von orgBild freigibt.
Der Zeiger von staticBild zeigt aber noch darauf und schon kracht es....
Dem kannst du aus dem Weg gehen indem du ne tiefe Kopie des "Inhalts" hinter dem Zeiger machst.MfG Spacelord
-
Spacelord schrieb:
...
Dem kannst du aus dem Weg gehen indem du ne tiefe Kopie des "Inhalts" hinter dem Zeiger machst.
MfG Spacelord
Danke, daran habe ich noch garnicht gedacht.
Wie würde das denn aussehen?
-
Naja du überschreibst die automatisch generierte Version vom operator=.
Darin prüfst du zuerst ob es ne Selbstzuweisung ist,falls nein gibst du den alten Speicher frei,besorgst dir neuen Speicher in der Größe wie ihn das Objekt das du zuweisen möchtest hat und kopierst dann den Inhalt vom zuzuweisenden Objekt in deinen neu besorgten Speicherbereich.
Zu guter letzt gibst du *this zurück.Kleines Beispiel:
#include <iostream> using namespace std; class A { public: //Der einfachheit halber als public int* p; size_t size; //Konstruktor A(size_t s=1):size(s) { p = new int[s]; //irgendwelche Werte eintragen for(int i=0;i<size;++i) p[i]=i; } //Destruktor ~A(){delete[]p;} A& operator=(const A& q) { if(this!=&q) { delete[]p; size= q.size; p= new int[size]; memcpy(p,q.p,size*sizeof(int)); } return *this; } void output()const { for(int z=0;z<size;++z) cout<<p[z]<<endl; } }; void TestFunktion(A& dasA) { A b(12);//temporäres A objekt dasA=b; } int main() { A a; a.output(); cout<<"TestFunktion aufrufen."<<endl; TestFunktion(a); a.output(); return 0; }
Das gleiche gilt übrigens auch für den Kopierkonstruktor!
Der automatisch generierte Kopierkonstruktor wird das gleiche Verhalten zeigen wie der Zuweisungsoperator und sollte deshalb auch überschrieben werden.MfG Spacelord
-
Danke für die Mühe Spacelord!!
Werde noch Heute versuchen es zu implementieren.