Problem mit Zeigern, die mit new erstellt worden sind
-
Hallo,
ich habe ein Verständnisproblem mit dem Anlegen von Zeigern auf dem Heap. Kurz zur Aufgabenstellung: ich arbeite bei der Darstellung meiner Animation in der Offscreentechnik. Auf dem Bildschirm sollen Messwerte grafisch dargestellt werden. Ein Thread bedient die Messkarte und schreibt Messwerte in Variablen der Doc-Klasse. Dort werden auch die darzustellenden Bildpunkte errechnet. Somit ist die Kapselung dieses Threads gewährleistet. Ich habe dazu in meiner Doc-Klasse zwei Membervariablen definiert:
CBitmap* m_pBitmap CBitmap* m_pBitmapCopyEs werden immer zwei benötigt, da die Copy einzig und allein dazu da ist, von der View-Klasse die Darstellung und somit den Zugriff zu realisieren, während der Workerthread bereits wieder Bildpunkte berechnet und in die andere Bitmap reinschreibt.
Im Konstruktor meiner Doc-Klasse wird folgender Code aufgerufen:
void CMyAppDoc::Erstelle_Bitmap(void) { CDC memDC; memDC.CreateCompatibleDC (NULL); CBitmap *pOldBitmap; COLORREF rgbColor; m_pBitmap = new CBitmap (); m_pBitmap->CreateBitmap (kViewSize_x, kViewSize_y, 1, memDC.GetDeviceCaps (BITSPIXEL), NULL); m_pBitmapCopy = new CBitmap (); m_pBitmapCopy->CreateBitmap (kViewSize_x, kViewSize_y, 1, memDC.GetDeviceCaps (BITSPIXEL), NULL); // Initialisieren der Bitmap zur Berechnung pOldBitmap = memDC.SelectObject (m_pBitmap); // Schwarz memDC.PatBlt (0,0,kViewSize_x,kViewSize_y,BLACKNESS); { int Hintergrundmodus=GetBkMode(memDC); SetBkMode(memDC,TRANSPARENT); rgbColor = RGB(255,255,255); CPen Pen_solid(PS_SOLID, 0, rgbColor); CPen Pen_dash(PS_DOT, 0, rgbColor); CPen* oldPen; oldPen = memDC.SelectObject(&Pen_solid); memDC.MoveTo((kViewSize_x/2),0); memDC.LineTo((kViewSize_x/2),(kViewSize_y)); memDC.SelectObject(&Pen_dash); int Breite_Fadenkreuz=40; memDC.MoveTo(Mittelpunkt_links.x,(Mittelpunkt_links.y-Breite_Fadenkreuz/2)); memDC.LineTo(Mittelpunkt_links.x,(Mittelpunkt_links.y+Breite_Fadenkreuz/2)); memDC.MoveTo(Mittelpunkt_rechts.x,(Mittelpunkt_rechts.y-Breite_Fadenkreuz/2)); memDC.LineTo(Mittelpunkt_rechts.x,(Mittelpunkt_rechts.y+Breite_Fadenkreuz/2)); memDC.MoveTo((Mittelpunkt_links.x-Breite_Fadenkreuz/2),Mittelpunkt_links.y); memDC.LineTo((Mittelpunkt_links.x+Breite_Fadenkreuz/2),Mittelpunkt_links.y); memDC.MoveTo((Mittelpunkt_rechts.x-Breite_Fadenkreuz/2),Mittelpunkt_rechts.y); memDC.LineTo((Mittelpunkt_rechts.x+Breite_Fadenkreuz/2),Mittelpunkt_rechts.y); memDC.SelectObject(oldPen); SetBkMode(memDC,Hintergrundmodus); } // Aufräumen memDC.SelectObject (pOldBitmap); }Zum Darstellen des Ganzen wird dann einfach in der OnDraw-Methode die Bitmap aus dem Speichergerätekontext auf den Bildschirm geblittet.
Das funktioniert auch soweit ganz gut. Problematisch wird das ganze, wenn ich einen neuen Messzyklus aufrufen möchte. Dazu lösche ich die beiden Bitmaps wie folgt:
void CMyAppDoc::Loesche_Bitmap(void) { if (m_pBitmap) delete m_pBitmap; if (m_pBitmapCopy) delete m_pBitmapCopy; }Der gleiche Code wird auch vom Destruktor der Doc-Klasse aufgerufen.
Jetzt das Problem: führe ich nur einen Messdurchgang aus funktioniert das Ganze wunderbar. Will der Nutzer einen neuen Messdurchgang durchführen (Klick auf einen Button) und überlegt es sich dann aber doch anders und beendet das Programm bekomme ich eine unbehandelte Ausnahme an der Stelle delete m_pBitmap. In diesem Falle wird diese Löschfunktion zweimal hintereinander aufgerufen. Die Prüfung, ob die Membervariable einen gültigen Zeiger auf ein CBitmap-Object hat, scheint hier positiv zu sein obwohl ich doch beim vorherigen Durchlauf den Zeiger mit delete freigegeben habe. Wo liegt hier der Fehler? Dieses Problem taucht nicht auf wenn ich lösche und mit new eine neue Bitmap anlege...
-
AndyDD schrieb:
void CMyAppDoc::Loesche_Bitmap(void) { if (m_pBitmap) delete m_pBitmap; if (m_pBitmapCopy) delete m_pBitmapCopy; }Wie wär es denn mit:
void CMyAppDoc::Loesche_Bitmap() { if (m_pBitmap) { delete m_pBitmap; m_pBitmap = 0; } if (m_pBitmapCopy) { delete m_pBitmapCopy; m_pBitmapCopy = 0; } }
-
jencas schrieb:
AndyDD schrieb:
void CMyAppDoc::Loesche_Bitmap(void) { if (m_pBitmap) delete m_pBitmap; if (m_pBitmapCopy) delete m_pBitmapCopy; }Wie wär es denn mit:
void CMyAppDoc::Loesche_Bitmap() { if (m_pBitmap) { delete m_pBitmap; m_pBitmap = 0; } if (m_pBitmapCopy) { delete m_pBitmapCopy; m_pBitmapCopy = 0; } }Die if's kannst dir sparen, das testet delete selber
void CMyAppDoc::Loesche_Bitmap() { delete m_pBitmap; m_pBitmap = 0; delete m_pBitmapCopy; m_pBitmapCopy = 0; }
-
Vielen Dank erst mal. Laut Debugger steht in der Tat in der Variablen der Wert 0x00000000, nach dem delete allerdings steht da immer 0xfeeefeee. Ist ja ein typischer Anfängerfehler, peinlich peinlich....

Aber korrekterweise schreibt man folgendes:void CMyAppDoc::Loesche_Bitmap() { delete m_pBitmap; m_pBitmap = NULL; delete m_pBitmapCopy; m_pBitmapCopy = NULL; }Warum wird aber der Wert der Membervariablen gerade auf diesen Wert gestetzt? Ich würde ja verstehen wenn die alte Zeigeradresse drin bleiben würde und man nur den Zeiger selbst löscht.
-
Ich weiss es nicht genau, aber ich glaube, dass hat damit zu tun, dass die Speicherverwaltung im Debug-Modus ein wenig anders funktioniert als in der Release Version. Und im Debug-Modus wird meines wissens halt der Zeiger auf 0xfeeefeee gesetzt, wenn man delete nutzt.
Kann mich da aber auch irren
-
Das kann schon sein. Aber ich würde den dann standardmäßig auf NULL setzen, dann würde dieses Problem nicht auftreten.
-
beim Aufräumen in der Funktion die Dein Bitmap erstellt, muss folgendes eingefügt werden...
bitmap.DeleteObject();
-
[quote="AndyDD"]Vielen Dank erst mal. Laut Debugger steht in der Tat in der Variablen der Wert 0x00000000, nach dem delete allerdings steht da immer 0xfeeefeee. Ist ja ein typischer Anfängerfehler, peinlich peinlich....

Aber korrekterweise schreibt man folgendes:void CMyAppDoc::Loesche_Bitmap() { delete m_pBitmap; m_pBitmap = NULL; delete m_pBitmapCopy; m_pBitmapCopy = NULL; }Nö nix korrekter Weise!
NULL gehört nicht zum C++ Standard und is nen define aus C. Daher wäre die 0 korrekt. da NULL aber meist immer da ist, machts dann doch keinen Unterschied^^
Außer das defines nicht soo schön sind
-
Ja ok, NULL ist ein define, ob das zum Standard gehört kann ich nicht sagen, also vielen Dank für die Info.
irgendwer schrieb:
beim Aufräumen in der Funktion die Dein Bitmap erstellt, muss folgendes eingefügt werden...
bitmap.DeleteObject();
Wo soll das eingefügt werden?