Einzelnen Beitrag anzeigen

Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#10

Re: String in Listview Data ?

  Alt 30. Mär 2010, 14:24
.Data ist nicht wirklich umständlich nutzbar ... es ist wie mit jedem anderen Zeiger/Pointer auch.
Und hier war nunmal die eigentlich gute Referenzzählung schuld, welche man durch solch einen Cast absichtlich umgeht.

Einziges Problem bei Properties ist, daß sie keinen gleichzeitigen Schreib- und Lesezugriff erlauben, weswegen String(item.Data):=irgendwas; nicht ging.



Die hoika schon sagte, wenn man auf was zeigen will, dann muß man dafür sorgen, daß dieses nicht in der Zwischenzeit freigegeben wird.
Wobei Objekte keine referenzzählung haben und man sie daher auch direkt, in einen Pointer gekastet, in Data eintragen könnte.

Delphi-Quellcode:
item.Data := Pointer(Test);
//auslesen
Test := PChar(item.Data);
//oder
Test := String(item.Data); // wenn Test ein String ist
ist praktisch das Selbe wie
Delphi-Quellcode:
item.Data := PChar(Test);
//auslesen
Test := PChar(item.Data);
außer daß bei PChar für einen Leerstring (nil) nicht nil, sondern ein Zeiger auf einen mit #0 gefüllten Speicherplatz übergeben wird.

Wird jetzt Test verändert, freigegeben oder verschoben, dann zeigt .Data natürlich immernoch auf die Stelle des "alten" Strings und somit teigt String(item.Data) nicht mehr auf einen String und es knallt oder es kommt im günstigsten Falle nur Schrott raus.

Delphi-Quellcode:
var
  P: Pointer;
  i: integer;
  item: TListItem;
begin
  for i := 0 to 10 do
  begin
    item := TListItem.Items.Add;
    item.caption := 'Test ' + IntToStr(i);
    String(P) := 'Ich liege in der Listview.Items.Item.data an der Stelle ' + IntToStr(i);
    item.Data := P;
  end;
end;
Delphi-Quellcode:
test := 'Ich liege in der Listview.Items.Item.data an der Stelle ' + IntToStr(i);
String(P) := test;
item.Data := P;
test := '';
Hier wird P wie eine Stringvariable behandelt, es wird also bei Zuweisung auch der Referenzzähler des String erhöht.
Gibt man nun test wieder frei, dann wird der Referenzzähler erniedrigt, aber da ja noch die Referenz für String(P) existiert, wird der String nicht freigegeben, sondern existiert weiterhin in P.
Die Folge ist nun, daß man beim löschen des Items auch den String in item.Data mit freigeben muß, da ja sonst ein Speicherleck entsteht.


Fazit:
Wird etwas direkt in .Data abgelegt, dann muß man es dort auch wieder freigeben,
auch wenn man ein Objekt nur da reinlegt.

Wärend bei hoikas Vorschlag das Objekt in einer externen Liste liegt und in P nur eine Kopie des Instanzzeigers.
Bei ihm muß/darf man das Objekt in .Data also nicht freigeben, da hierfür die Liste verantwortlich ist, welche ja quasi das Original besitzt.
$2B or not $2B
  Mit Zitat antworten Zitat