Speicherbereich von Element wird überschrieben
-
Hallo Alle zusammen,
ich hab ein ziemlich komisches Problem, und weiss nicht recht genau, wie ich das erklären soll. Also ich hab eine Klasse A definiert, welche verschiedene Elemente und Methoden implementiert hat. Auf diese Elemente greife ich über die Methoden drauf zu, alle Elemente sind dann private und die Methoden klar public. Nun habe ich eine Instanz von der Klasse A in einer anderen Klasse B angelegt, das ist meine sozusagen Basisklasse, von der aus ich verschiedene Klassen C,D,E noch aufrufe. Um auf das gleiche Objekt der Klasse A immer zugreifen zu können, verzweige ich mit dem Zeiger aus den verschiedenen Klassen C,D,E auf das Objekt der Klasse A in der Klasse B.
Nach paar Manipulierungen der Elemente der Klasse A, werden einige Elemente überschrieben, obwohl ich diese überhaupt nicht angefasst habe. Jetzt frage ich mich warum...
...hier noch ein paar Code-Schnipsel:Klasse A Header:
... private: CString arrayT1[30][8]; CString m_z_dbUser; CString m_z_dbName; CString m_z_servername; CString m_z_servertype; CString m_q_dbUser; CString m_q_dbName; CString m_q_server; CString m_q_servertype; CString m_q_db_password; CString m_q_sa_password; CString m_q_repository; CString m_plan_owner; CString m_log_verzeichnis; CString m_export_verzeichnis; CString m_z_db_password; CString m_z_sa_password; CString m_z_repository; CString m_paketname; CString m_system; public: void SetZielDBUser(CString dbuser); CString GetZielDBUser(); void SetZielDBName(CString dbname); CString GetZielDBName(); void SetZielServerName(CString servername); CString GetZielServername(); void DeleteArray(); ...Verzweigen auf den Zeiger der Klasse B (Objekt der Klasse A erstellt) in Klassen C,D,E:
Klasse_B* Klasse_B_objekt = (Klasse_B*)AfxGetMainWnd(); Klasse_B_objekt->Klasse_A_objekt.SetSystem(value); //!!...an dieser Stelle (!!) sind die Elemente der Klasse A noch so, wie ich sie will
...nach dem Aufruf der Methode DeleteArray() werden auf einmal alle anderen Elemente auch gelöscht, obwohl diese nicht von betroffen sind.
Klasse_B* Klasse_B_objekt= (Klasse_B*)AfxGetMainWnd(); Klasse_B_objekt->Klasse_A_objekt.DeleteArray(); //Aufruf DeleteArray() m_system= Klasse_B->Klasse_A_objekt.GetSystem();//Element m_system plötzlich leer!!!!Methode DeleteArray:
void Klasse_A::DeleteArray() { for (int i=0;i<=30;i++) { for (int j=0;j<=7;j++) { arrayT1[i][j] = ""; } } }Weiss jemand vielleicht ne Erklärung zu?
Gruss,
chullain
-
Und Du bist sicher, dass Dein MainWnd vom Typ Klasse_B ist, bzw. von Klasse_B direkt abgeleitet ist?
Klasse_B* Klasse_B_objekt= (Klasse_B*)AfxGetMainWnd();Oder hast Du hier etwa mehrfach Vererbung verwendet.
Wie ist Dein CMainWnd deklariert?
-
nein, es findet keine Vererbung statt, ich erstelle nur eine Instanz in der CWinApp-Klasse von meiner Klasse_B und übertrage die Adresse des Zeigers an m_pMainWnd, also so:
CMenue dlg; m_pMainWnd = &dlg;...in der Klasse B lege ich ne Instanz der Klasse A an...
class Klasse_B: public CDialog { ... Klasse_A container; ... }...um dann in den anderen Klassen C,D,E auf das Objekt der Klasse A zugreifen zu können:
Klasse_B* Klasse_B_objekt= (Klasse_B*)AfxGetMainWnd(); m_system= Klasse_B->container.GetSystem();...oder muss ich die Klasse A am Besten in der CWinApp Klasse schon mal anlegen und dann über den MainWnd aus den Kalssen C,D,E auf die CWinApp-Klasse zugreifen?
Gruss,
chullain
-
Das MainWnd ist, wenn ich jetzt deinen Code richtig deute, ein CMenu-Objekt (schon diese Zuweisung sollte imho nicht funktionieren) - das wandelst du um in ein Klasse_B-Objekt, das damit überhaupt nicht verwandt ist. Also interpretierst du irgendwelche (möglicherweise unbelegten) Speicherbereiche als Klasse_B, da kann nur Müll herauskommen.
(Und nebenbei wird das lokal angelegte Objekt, das du als Hauptfenster angemeldet hast, am Ende der Init-Funktion wieder pulverisiert)
-
wie spreche ich dann das Objekt der Klasse A aus den Klassen C,D,E an, wenn ich das Objekt der Klasse A in der Klasse B erstellt habe. Ich meine das Objekt der Klasse B ist die ganze Zeit aktiv, auch wenn ich andere Dialogfenster der Klassen C,D,E auf habe...
...über referenzierung klappt das irgendwie auch nicht...
Gruss,
chullain
-
Solange du das Klasse_B-Objekt hast, kannst du über . (bei Zeigern ->) auch auf dessen Member zugreifen. Aber aus deinem Code kann man nicht erkennen, wo das Objekt angelegt wurde (und das ist wichtig um zu wissen, ob es noch exisitert).
-
..also in der Klasse B werden alle anderen Objekte (Dialoge) erzeugt, jedoch schliesse ich nicht das Objekt der Klasse_B
void Klasse B::OnRepositoryOperation() { ... Klasse_C repoOperation(this); ... }BOOL Klasse_C::OnSetActive() { ... Klasse_B* Klasse_B_objekt= (Klasse_B*)AfxGetMainWnd(); ... }...irgendwann überschreibe ich nur den Speicherbereich einer Variable, denn ich eigentlich überhaupt nicht angefasst habe...und das ist ärgerlich...
Gruss,
chullain
-
chullain schrieb:
..also in der Klasse B werden alle anderen Objekte (Dialoge) erzeugt, jedoch schliesse ich nicht das Objekt der Klasse_B
Ja, sehr schön - aber WO LEGST DU DEIN 'Klasse_B' OBJEKT AN? Bevor du diese Frage nicht beantwortet hast, kommen wir nicht weiter.
-
ja, hab ich doch schon erwähnt in meiner CWinApp-Klasse, also der Hauptklasse der Anwendung...
Header:
class CAPIApp : public CWinApp { public: CAPIApp(); ... }*.cpp
BOOL CAPIApp::InitInstance() { ... Klasse_B dlg; m_pMainWnd = &dlg; ... }
-
chullain schrieb:
BOOL CAPIApp::InitInstance() { ... Klasse_B dlg; m_pMainWnd = &dlg; ... }Und da haben wir auch schon das Problem. Dein Objekt 'dlg' liegt lokal in der InitInstance()-Methode. Das bedeutet, am Ende der Methode wird es wieder demontiert und sein Speicherplatz kann von der nächsten verwendeten Funktion neu überschrieben werden. Leg das Objekt also besser an einem Ort an, wo es bis zum Programmende überleben kann, z.B. als static Variable in der InitInstance(), als globale Variable oder als Member der CAPIApp-Klasse (ich würde letzteres bevorzugen).
-
@CStoll:
Aber wenn es das normale Design einer Dialog-Applkation ist, dann ist dieses Objekt so lange gültig, wie auch DoModal läuft.@chullain:
Aber das eigentliche Problem sehe ich jetzt:// Deklaration CString arrayT1[30][8]; // Code void Klasse_A::DeleteArray() { for (int i=0;i<=30;i++) { // ^ HIER IST DER BUG! for (int j=0;j<=7;j++) { arrayT1[i][j] = ""; } } }Array überlauf! Du darfst nur bis <30 gehen!
Gewöhne dir immer an mit < zu testen und den die Größe des Arrays als Vergleichswert zu nutzen.
Noch besser Du verwendest _countof oder einen ähnlichen Makro:
void Klasse_A::DeleteArray() { for (int i=0; i<_countof(arrayT1); ++i) { for (int j=0; j<_countof(arrayT1[0]); ++j) arrayT1[i][j].Empty(); } }BTW: Zum Löschen von CString verwende Empty()!
-
das wars gewesen, vielen lieben Dank.
Gruss,
chullain