Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Pointer von AddObject wieder freigeben (https://www.delphipraxis.net/56420-pointer-von-addobject-wieder-freigeben.html)

Pfoto 5. Nov 2005 12:32


Pointer von AddObject wieder freigeben
 
Hallo zusammen,

Ich möchte mir in einer Listbox einen Integer-Wert merken.

Dazu benutze ich
Delphi-Quellcode:
Listbox.Items.AddObject('Item 1', Pointer(IntegerWert));
oder sollte ich
Delphi-Quellcode:
Listbox.Items.AddObject('Item 1', TObject(IntegerWert));
benutzen?

Und wie das Ganze freigeben?
Reicht es, wenn ich
Delphi-Quellcode:
Listbox.Items.Objects[index].free
aufrufe oder muss ich noch etwas anderes machen? :gruebel:



Dank und Gruß
Pfoto

chaosben 5. Nov 2005 13:32

Re: Pointer von AddObject wieder freigeben
 
Hi Pfoto!

Du bist schon ziemlich nah dran. Das Merken funktioniert so (wie du das schon richtiger-weise erkannst hast):
Delphi-Quellcode:
Listbox.Items.AddObject('Item 1', TObject(IntegerWert));
Den Wert bekommt du dann über:
Delphi-Quellcode:
Integer(Listbox.Items.Objects[1])
Freigeben musst du hier nichts, weil du zum Merken des Wertes einen Speicherbereich nimmst, der von der Stringlist genutzt wird. Dieser Bereich wird beim "Items.Add" reserviert und beim "Items.Delete" o.ä. wieder freigeben. Ein Free an dieser Stelle ist überflüssig bzw. sogar eine Fehlerquelle denn: Nehmen wir an du merkst dir einen Int-Wert 576 so:
Delphi-Quellcode:
Listbox.Items.AddObject('Item 1', TObject(576));
. Wenn du dann ein Free aufrufst, würde Delphi bzw. dein Programm versuchen, ein angenommenes TObject ab der Adresse $240 (dez: 576) im RAM freizugeben. Dies wiederum könnte zu einer EAccessVioalation führen.
So, genug geschwafelt, wahrscheinlich hast du das alles schon geahnt. :)

Pfoto 5. Nov 2005 14:10

Re: Pointer von AddObject wieder freigeben
 
Danke chaosben,

was mich verwirrt hat war nur, dass in der Hilfe zu AddObject steht, das die Liste nicht Eigentümer des Objektes wäre und deshalb das Objekt auch noch im Speicher verbliebe, selbst wenn die Liste gelöscht wird.

Und noch was (zum Verständnis): Was bedeutet es denn wenn ich Pointer(IntegerWert) übergebe?
Wird bei einem TObject nicht auch nur ein Pointer übergeben?
Warum muss ich für so einen kleinen Integer-Wert ein so "großes" Object übergeben? :?:

Dank und Gruß
Pfoto

Muetze1 5. Nov 2005 14:22

Re: Pointer von AddObject wieder freigeben
 
Das ist es ja: du übergibst ja kein Objekt.

Eine Variable von TObject wäre nur der Speicherplatz für einen Zeiger wo im Speicher das Objekt liegt. Dieser Speicherplatz wird beim Constructor alloziiert und im Destructor wieder freigegeben.

Die TStringList hat nun vorgesorgt und für jeden String auch gleich Platz für einen Zeiger gehalten. Dort wird dann die Adresse des Objektes eingetragen, wenn du eins hinzufügst. Dieser Speicherplatz für den Pointer ist 4 Byte gross (siehe auch SizeOf(TObject)). Und genauso gross ist auch ein Integer. Dass bedeutet du benutzt den Speicherplatz wo der Pointer abgelegt wird und legst statt einer Adresse deine Zahl (Integer) ab. Nun will aber TStringList ein Objekt als Typ haben bei AddObjekt und daher meckert der Compiler. Darum sagst du dem Compiler mit TObject(deinInteger) einfach: "Hör zu - auch wenn es so aussieht - das ist kein Integer - das ist ein Objekt, also nimm den". Da sich die TStringList eh nur die Adresse des Objektes vermerkt und ihr es egal ist wie gross und wo das Objekt liegt, passt das. Sie vermerkt sich dein Integerinhalt als Adresse und führt ihn mit. Da die TStringList nix mit den Objekten macht sondern nur die Adressen verwaltet, gibs soweit auch keine Probleme.

Das Objekt müsstest du freigeben - du hast aber kein Objekt. Du sagst dem Compiler nur, das ist eins (bzw. behandle es wie eins), aber du legst ja keins an. Daher auch nix freizugeben.

chaosben 5. Nov 2005 14:38

Re: Pointer von AddObject wieder freigeben
 
Ich versuchs noch mal ein wenig plastisch darzustellen:

Wenn du einer StringList ein Item hinzufügst sieht das im Speicher etwa so aus:
Code:
[Hier steht der Text des Items][$00000000]
Die 0en am Ende sollen 4 Byte reservierten Ram darstellen.
Wenn du nu
Delphi-Quellcode:
Items.AddObject('Tolle Sache das',TObject(Button1))
ausführst, sieht dein Programm nach, wo im Speicher denn Button1 liegt. Nehmen wir an, der Button liegt bei $AB23 im RAM dann sieht dein Item im Speicher etwa so aus:
Code:
[Tolle Sache das][$0000AB23]
Wenn du dagegen dir einen Int-Wert merkst, dann sieht es nach
Delphi-Quellcode:
Items.AddObject('Item1', TObject(576))
etwas so aus:
Code:
[Item1][$00000240]
Wenn du das Item löscht, kümmert sich die StringList selbst drum, die 4 Bytes am Ende mit freizugeben, da sie diese ja auch selbst angelegt hat.

Pfoto 5. Nov 2005 14:57

Re: Pointer von AddObject wieder freigeben
 
Ahhhh!

Herzlichen Dank an Euch Beide! Jetzt ist endlich der Groschen gefallen... :bounce1:


Gruß
Pfoto


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:44 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz