Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » VC++ / MFC » Problem mit Zeigern, die mittels new erstellt worden sind

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
08.09.2006, 12:08 Uhr
AndyDD



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:

C++:
CBitmap*  m_pBitmap
CBitmap*  m_pBitmapCopy



Es 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:



C++:
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:


C++:
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...
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
08.09.2006, 13:00 Uhr
FloSoft
Medialer Over-Flow
(Administrator)


darum setzt man ausnahmsweise gelöschte Pointer danach auf NULL, denn ein delete/free auf NULL wird ignoriert.
--
class God : public ChuckNorris { };
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
08.09.2006, 13:19 Uhr
AndyDD



Ja vielen Dank, so funktioniert es auch. Ist ja ein typischer Anfängerfehler. Peinlich peinlich....
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
08.09.2006, 17:15 Uhr
Tommix



Hallo,
die oft zu sehende Abfrage
C++:
if (zeiger) delete zeiger;


ist in aus dem von Flo genannten Grund überflüssig.

C++:
delete zeiger;


reicht.

- Tommix
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
11.09.2006, 07:39 Uhr
AndyDD



Vielen Dank Euch beiden, so funktionierts nun prima. Aber noch eine Frage. Muss man die Bitmaps mit DeleteObjects freigeben?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
11.09.2006, 08:41 Uhr
Tommix



'Morgen,
nein, das macht der Dtor von CGdiObject.
Siehe MSDN:

Zitat:

When you finish with the CBitmap object created by the CreateBitmap function, first select the bitmap out of the device context, then delete the CBitmap object.



Gruß, Tommix

Dieser Post wurde am 11.09.2006 um 08:41 Uhr von Tommix editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
11.09.2006, 08:47 Uhr
AndyDD



Ebenfalls guten Morgen, vielen Dank für die Antwort. Dachte ich mir auch schon, aber es wurde in einem anderen Post empfohlen. Der Dtor des CBitmap-Objects wird ja durch den Dtor meiner Doc-Klasse aufgerufen. Aber rein theoretisch könnte man doch anstatt der delete-Variante auch mit DeleteObjects arbeiten, oder?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
11.09.2006, 09:05 Uhr
Tommix



Nein. Ein mit new erzeugtes Objekt wird mit delete gelöscht. DeleteObject löscht nur das zugehörige Windows-GDI-Object, nicht das CBitmap selbst.

- Tommix
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ VC++ / MFC ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: