Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Problem mit TList / Pointern
P@u1 - Mi 17.11.10 23:37
Titel: Problem mit TList / Pointern
Hi,
ich habe gerade ein Problem mit Pointern und habe den Verdacht, dass Delphi automatisch Objekte freigibt (ich war immer davon ausgegangen, dass Objekte nur freigegeben werden, wenn man das selbst explizit macht).
Zur Erklärung: TBitMapEx ist eine Erweiterung von TBitMap und hat z.B. die Methode GetScreenShot, deren Funktion offensichtlich sein sollte.
Ich habe eine FormCreate-Methode die so aussieht:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| procedure TForm1.FormCreate(Sender: TObject); var Pbmp : ^TBitMapEx; bmp : TBitMapEx; begin List := TList.Create; bmp := TBitMapEx.Create; Pbmp := @bmp; Pbmp^.GetScreenShot; List.Add(Pbmp); Image1.Picture.Bitmap := TBitMapEx(List.Items[0]^); end; |
Das ganze funktioniert auch.
Aber wenn ich jetzt im Button1Click folgendes mache:
Delphi-Quelltext
1: 2: 3: 4:
| procedure TForm1.Button1Click(Sender: TObject); begin Image1.Picture.Bitmap := TBitMapEx(List.Items[0]^); end; |
Gibt es eine Zugriffsverletzung!
Es wurde also das mit
Delphi-Quelltext
1:
| bmp := TBitMapEx.Create; |
So wie ich das sehe automatisch freigegeben.
Wenn ich bmp global definiere, passiert das nicht.
Wieso wird das denn freigegben, es ist doch ein Objekt!
Und wie kann ich das Verhindern?
Ich möchte das Objekt ja später noch über die Liste ansprechen können.
Dann hab ich noch was mit dem Befehl new versucht:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7:
| procedure TForm1.FormCreate(Sender: TObject); var Pbmp : ^TBitMapEx; begin new(Pbmp); Pbmp^.GetScreenShot; end; |
Gibt auch einen Error (Zugriffsverletzung).
Erstellt das new nicht auch eine Instanz, oder wie funktioniert das?
Ich bin jetzt gerade extremst verwirrt und hoffe auf Hilfe!
Dude566 - Do 18.11.10 00:15
Ich nehme mal an, dass nicht das Objekt gelöscht wird, sonder lediglich der Verweis (Instanzvariable), da diese nur lokal in der Funktion deklariert ist. ;)
bummi - Do 18.11.10 00:28
Du erzeugst das Objekt, die Referenz liegt bei Dir auf dem Stack, interessanterweise übergibst Du dann noch eine Zeiger auf diese Stackvariable an die Liste.
In der Liste sind dann Zeiger auf den Stack, welcher sich permanent ändert ;-).
Warum nicht einfach
Delphi-Quelltext
1:
| List.add(TBitmapEx.Create); |
Dude566 - Do 18.11.10 00:32
Ich habe sowieso nicht verstanden, warum du den Pointer in FormCreate brauchst.
jaenicke - Do 18.11.10 06:58
P@u1 hat folgendes geschrieben : |
Gibt auch einen Error (Zugriffsverletzung).
Erstellt das new nicht auch eine Instanz, oder wie funktioniert das? |
Nein, mit New kannst du Speicher für einen Pointer reservieren. Zum Beispiel für einen Pointer auf einen Record, dann wird so viel Speicher reserviert wie der Record groß ist.
So, du reservierst also 4 Byte (unter 32-Bit), denn so groß ist das Ziel deines Pointers. Denn das Ziel deines Pointers ist nur wieder ein Pointer auf die eigentliche Bitmap.
Nebenbei rate ich dir für Objekte zu TObjectList. Die kannst du da direkt als Objekte hineinpacken. (ab Delphi 2009 sogar direkt typisiert, vorher nur manuell). Die gibt dann auf Wunsch beim Löschen eines Objekts aus der Liste oder beim Zerstören der Liste die passenden Objekte automatisch frei.
P@u1 - Do 18.11.10 10:45
Das mit der Objektlist ist ein guter Tipp, danke.
Nur ich habs nicht hinbekommen, dass typisiert zu verwenden, ich habs so versucht:
Delphi-Quelltext
1:
| ObjList : TObjectList<TBitMapEx>; |
Oder geht das bei Delphi irgendwie anders?
Und falls ichs untypisiert verwende, dann hat das zur Folge, dass ich, wenn ich ein Element benutzen will es erst auf BitMapEx casten muss, richtig?
Und dann noch mal zu den Pointern, ist das bei Delphi so, dass wenn ich folgendes mache:
Delphi-Quelltext
1:
| bmp := TBitMapEx.Create; |
in bmp automatisch nur ein Pointer gespeichert wird und ich deswegen einen Pointer auf einen Pointer hatte, der nur lokal definiert war und deswegen danach nicht mehr erreichbar war, oder hab ich was falsch verstanden?
Das heißt, dass Konzept davon ist gleich oder sehr ähnlich zu Java?
Das würde dann ja heißen, dass ich bmp direkt in die List reinpacken kann ohne @ zu benutzen.
jaenicke - Do 18.11.10 11:29
P@u1 hat folgendes geschrieben : |
| Nur ich habs nicht hinbekommen, dass typisiert zu verwenden, ich habs so versucht: |
Welche Delphiversion? Und was ist passiert?
P@u1 hat folgendes geschrieben : |
| Und falls ichs untypisiert verwende, dann hat das zur Folge, dass ich, wenn ich ein Element benutzen will es erst auf BitMapEx casten muss, richtig? |
Ja
P@u1 hat folgendes geschrieben : |
| in bmp automatisch nur ein Pointer gespeichert wird und ich deswegen einen Pointer auf einen Pointer hatte, der nur lokal definiert war und deswegen danach nicht mehr erreichbar war, oder hab ich was falsch verstanden? |
Nein, das hast du richtig verstanden.
P@u1 hat folgendes geschrieben : |
| Das heißt, dass Konzept davon ist gleich oder sehr ähnlich zu Java? |
Bei Objekten gilt das meistens, auch in anderen Sprachen. Bei Records und sowas natürlich nicht.
P@u1 hat folgendes geschrieben : |
| Das würde dann ja heißen, dass ich bmp direkt in die List reinpacken kann ohne @ zu benutzen. |
Ja.
P@u1 - Do 18.11.10 16:30
Vielen Dank für die Hilfe!
Ich verwende Delphi 2010.
Allein beim Deklarieren passiert schon folgendes:
Delphi-Quelltext
1: 2: 3:
| var Form1: TForm1; ObjList : TObjectList<TBitMapEx>; |
[DCC Fehler] Unit1.pas(20): E2003 Undeklarierter Bezeichner: 'TObjectList<>'
Bergmann89 - Do 18.11.10 16:32
Hey,
such mal in der Delphi Hilfe nach TObjectList, da steht welche Units du einbinden musst (hab sie jetzt nicht im Kopf).
€: ich weiß auch nicht ob man die TObjectList typisieren kann, kann aber dein das es bei D2010 schon funktioniert, ich arbeite noch mit D7.
MfG Bergmann
P@u1 - Do 18.11.10 16:41
untypisiert reicht es, wenn ich Contnrs einbinde.
Typisiert funktioniert damit nicht, aber ich guck jez mal eben in der Hilfe.
Edit: Mir fällt gerade auf, dass ich vergessen hab, die Hilfe zu installieren bisher... ich guck mal kurz im Internet ob ich was brauchbares finde.
bummi - Do 18.11.10 16:44
nimm Generics.Collections in die uses auf....
P@u1 - Do 18.11.10 16:46
Habs gerade gefunden, aber trotzdem vielen Dank!
Funktioniert jetzt alles wunderbar und ich hab die Sachen jetzt auch verstanden mit dem doppeltem Pointer und so, was ich falsch gemacht habe. Ich markier also mal als erledigt, vielen Dank an alle, die mir geholfen haben.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!