Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Lebensdauer einer Stringlist (https://www.delphipraxis.net/186281-lebensdauer-einer-stringlist.html)

idefix2 19. Aug 2015 19:21

Lebensdauer einer Stringlist
 
Beim Programmstart erzeuge ich im Formcreate des Hauptformulars eine lokale Stringlist, die ich einer Reihe von Dropdown-Boxen als Itemliste zuordne.
Die lokale Variable vom Typ TStringlist verschwindet natürlich beim Beenden von Formcreate.
Auf diese Art produziere ich allerdings vermutlich ein Speicherleck, das sich natürlich erst beim Beenden des Programms manifestiert - bis dahin wird die Stringlist von den Dropdown-Boxen ja gebraucht - und daher nichts wirklich Böses anrichten kann.

Würdet ihr die Variable extra in den private-Bereich der Form übersiedeln, um beim Programm Beenden die Stringlist wieder freizugeben? Wäre das für irgend etwas gut?

Sir Rufo 19. Aug 2015 19:26

AW: Lebensdauer einer Stringlist
 
Keine deiner ComboBoxen braucht die nachher noch.

Du kannst die StringList beruhigt direkt in der Methode wieder freigeben.

Dejan Vu 19. Aug 2015 19:35

AW: Lebensdauer einer Stringlist
 
Speicherlecks findet man zuverlässig mit Bordmitteln und/oder FastMM, zu dessen Verwendung ich dringend rate.

Aviator 19. Aug 2015 20:15

AW: Lebensdauer einer Stringlist
 
Zitat:

Zitat von Dejan Vu (Beitrag 1312779)
Speicherlecks findet man zuverlässig mit Bordmitteln und/oder FastMM, zu dessen Verwendung ich dringend rate.

Er weiß doch woher sein Speicherleck kommt. Nur war seine Frage, wann er denn die StringList wieder freigeben kann. Da die Items aus der StringList wohl in seine ComboBoxen "kopiert" werden, braucht er die StringList nicht mehr und kann diese deshalb im FormCreate, wie von Sir Rufo bereits angemerkt, direkt wieder freigeben.

idefix2 19. Aug 2015 21:27

AW: Lebensdauer einer Stringlist
 
Ah, danke. Das war mir nicht klar.
Ich war der Meinung, die verschiedenen Comboboxen verweisen dann nur auf die eine Stringlist. Dann ist es einfach.

Verstehe ich allerdings nicht ganz, weil die Zuweisung eines TObject doch normalerweise keine Kopie anlegt, dazu ist doch "assign" notwendig (das ich nicht verwendet habe, weil ich mir gedacht habe, einmal reicht, der Inhalt wird im ganzen Programmlauf nicht mehr geändert). Warum ist das in dem Fall anders?

Sir Rufo 19. Aug 2015 21:33

AW: Lebensdauer einer Stringlist
 
Das siehst du, wenn du dir den Setter von
Delphi-Quellcode:
TComboBox.Items
anschaust.

Was finden wir da? Ein
Delphi-Quellcode:
Assign
;)

Und die Items sind sowieso keine
Delphi-Quellcode:
TStringList
, somit würde eine reine Zuweisung nicht funktionieren.

idefix2 20. Aug 2015 07:55

AW: Lebensdauer einer Stringlist
 
Zitat:

Zitat von Sir Rufo (Beitrag 1312795)
Das siehst du, wenn du dir den Setter von
Delphi-Quellcode:
TComboBox.Items
anschaust.

Was finden wir da? Ein
Delphi-Quellcode:
Assign
;)

Ein assign im Setter, das ist fies...
Der Nachteil von OOP ist wohl, dass man sich auf nichts wirklich verlassen kann.


Zitat:

Zitat von Sir Rufo (Beitrag 1312795)
Und die Items sind sowieso keine
Delphi-Quellcode:
TStringList
, somit würde eine reine Zuweisung nicht funktionieren.

Aber TStringlist ist doch Nachkomme von TStrings, so eine Zuweisung muss doch ganz normal funktionieren. Es ist doch im Gegenteil so, dass TStrings eine virtuelle Klasse ist und direkt gar nicht instanziiert werden kann (soll).

Jumpy 20. Aug 2015 08:48

AW: Lebensdauer einer Stringlist
 
Zitat:

Zitat von idefix2 (Beitrag 1312821)
Es ist doch im Gegenteil so, dass TStrings eine virtuelle Klasse ist und direkt gar nicht instanziiert werden kann (soll).

Meinst du vielleicht abstrakte (statt virtuelle) Klasse? Das sind die, die man nicht direkt erstellen kann, sondern erst die Nachfahren.

frankyboy1974 20. Aug 2015 09:43

AW: Lebensdauer einer Stringlist
 
Hallo,

es gibt in Delphi abstrakte Methoden (eine Methode die deklariert aber nicht implementiert ist). Daneben kann ich eine Methode als virtuell deklarieren (bzw. als dynamic, meint grundsätzlich das gleiche). Damit erreicht man dann polymorphes Verhalten, man deklariert in der Oberklasse eine virtuelle Methode (kann ggf. auch abstrakt sein), und in den verschiedenen Unterklassen überschreibt man dann die virtuelle Methode. Nun wird erst zur Laufzeit entschieden, wessen Methode tatsächlich ausgeführt wird (spätes Binden).

Eine Klasse die mindestens eine abstrakte Methode enthält, bezeichnet man dann gemeinhin als abstrakte Klasse. In Delphi kann man (anders als beispielsweise in Java), auch Instanzen von abstrakten Klassen erzeugen. Ruft man nun aber zur Laufzeit eine abstrakte Methode auf, erhält man eine entsprechende Fehlermeldung.

Ich wollte nur mal ein wenig klug sch.. Damit die Begrifflichkeiten, nicht ganz so durcheinander gewürfelt werden.:stupid:

mfg

frank

DeddyH 20. Aug 2015 12:39

AW: Lebensdauer einer Stringlist
 
Zitat:

Zitat von idefix2 (Beitrag 1312821)
Ein assign im Setter, das ist fies...

Ich würde eher im Gegenteil behaupten, das ist mal nachgedacht, um Dangling Pointer durch unbedachte Zuweisung zu verhindern. Und wenn man sich nicht sicher ist (oder die Sourcen nicht hat), ruft man eben selbst Assign auf.
Delphi-Quellcode:
var
  MyStrings: TStringlist;
begin
  MyStrings := TStringlist.Create;
  try
    MyStrings.Add('Eins');
    MyStrings.Add('Zwei');
    MyStrings.Add('Drei');
    SomeComboBox.Items.Assign(MyStrings);
  finally
    MyStrings.Free;
  end;
end;

Sir Rufo 20. Aug 2015 12:45

AW: Lebensdauer einer Stringlist
 
Und die Doku zu Delphi-Referenz durchsuchenTComboBox.Items ist da auch eindeutig:
Zitat:

Durch eine Zuweisung an Items können Sie die Elemente einer anderen Stringliste in die Liste des Kombinationsfeldes kopieren.
;)

DeddyH 20. Aug 2015 12:58

AW: Lebensdauer einer Stringlist
 
Gelegentlich verfügt die Doku zurzeit auch über zusätzliche Informationen (kommt ja nicht sooo oft vor :stupid:).

idefix2 20. Aug 2015 18:43

AW: Lebensdauer einer Stringlist
 
Zitat:

Zitat von Jumpy (Beitrag 1312823)
Zitat:

Zitat von idefix2 (Beitrag 1312821)
Es ist doch im Gegenteil so, dass TStrings eine virtuelle Klasse ist und direkt gar nicht instanziiert werden kann (soll).

Meinst du vielleicht abstrakte (statt virtuelle) Klasse? Das sind die, die man nicht direkt erstellen kann, sondern erst die Nachfahren.

Richtig, abstrakt habe ich gemeint.

Zitat:

Zitat von Sir Rufo (Beitrag 1312867)
Und die Doku zu Delphi-Referenz durchsuchenTComboBox.Items ist da auch eindeutig:
...
;)

Ja, dazu muss man erst einmal auf die Idee kommen, dass die VCL da mit dem Setter eine Schweinerei machen könnte - sonst gibt es nämlich keine Veranlassung, extra in der Hilfe nachzulesen. Die Zuweisung von Objekten weist eben normalerweise nur die Referenz auf die Objekte zu, warum das im Fall der Kombobox von Delphi anders ablaufen muss und das Kopieren der Daten über den Setter erzwungen wird, leuchtet mir nicht wirklich ein.

Sir Rufo 20. Aug 2015 18:53

AW: Lebensdauer einer Stringlist
 
Soweit wie ich das gesehen habe, werden in der VCL nur Referenzen zu Komponenten übergeben (die können überwacht werden). Alle andere Instanzen werden kopiert (internes Assign).

Es gibt Ausnahmen, die aber auch ansonsten aus dem normalen VCL Rahmen fallen.

idefix2 20. Aug 2015 19:12

AW: Lebensdauer einer Stringlist
 
Danke für den Hinweis, es ist dann sicher gut, das im Hinterkopf zu behalten.

Nachdem sich die Stringlist in meinem Programm nicht ändert und die Strings selbst auch nur Referenzen sind, ist es mir egal, ob hier Kopien erstellt werden.
Lästig wird es, wenn sich die Stringlist irgendwann doch ändern kann, und bei jeder Änderung immer alle 20 Kopien aktualisiert werden müssen. Dann würde ich mir wohl eine Kombobox ableiten, die das anders macht.

TBx 20. Aug 2015 19:40

AW: Lebensdauer einer Stringlist
 
Also erstens mal würde ich da gewiss nicht die Funktionalität der Combobox ändern, sondern höchstens eine Methode schreiben, die eben alle Comboboxen mit neuen Items versieht.
Weiters frage ich mich, wozu man zwanzig identische Comboboxen benötigt. Klingt nicht sonderlich übersichtlich.

idefix2 21. Aug 2015 05:59

AW: Lebensdauer einer Stringlist
 
Zitat:

Zitat von TBx (Beitrag 1312934)
Also erstens mal würde ich da gewiss nicht die Funktionalität der Combobox ändern, sondern höchstens eine Methode schreiben, die eben alle Comboboxen mit neuen Items versieht.

Und warum? Was ist sinnvoll daran, 20 Kopien der gleichen Daten im Speicher zu halten, und ständig parallel zu aktualisieren, wenn Referenzen auf eine Kopie dieser Daten genügen?

Sir Rufo 21. Aug 2015 06:19

AW: Lebensdauer einer Stringlist
 
Wenn du das Pferd etwas anders aufsattelst, dann wird die Umsetzung einfacher, weil du die ComboBox nicht ändern musst.

Erstelle dir eine Komponente, die nur eine Stringlist verwaltet und wo du andere Komponenten (z.B. ComboBoxen) registrieren kannst. Jede Änderung an der Strings-Komponente veranlasst diese alle registrierten Komponenten zu aktualisieren.

idefix2 21. Aug 2015 06:40

AW: Lebensdauer einer Stringlist
 
Jetzt habe ich in den VCL-Sourcen den Setter gesucht - Entweder ich verstehe es nicht oder das ist wirklich totaler Schwachsinn:

Delphi-Quellcode:
procedure TCustomCombo.SetItems(const Value: TStrings);
begin
  if Assigned(FItems) then
    FItems.Assign(Value)
  else
    FItems := Value;
end;
Also: Wenn in Items schon vorher etwas anderes dringestanden ist, dann wird mittels assign kopiert, andernfalls wird nur die Referenz zugewiesen.

Was soll das ??????

Sir Rufo 21. Aug 2015 06:59

AW: Lebensdauer einer Stringlist
 
Du musst immer das große Ganze betrachten um zu verstehen

So sieht die Ableitungskette aus:
Delphi-Quellcode:
TCustomCombo
<-
Delphi-Quellcode:
TCustomComboBox
<-
Delphi-Quellcode:
TComboBox
und hier werden die Items erzeugt
Delphi-Quellcode:
constructor TCustomComboBox.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  // Statt
  FItems := GetItemsClass.Create; // <- da ist
  // wäre auch das hier möglich
  // SetItems( GetItemsClass.Create );
  TCustomComboBoxStrings(FItems).ComboBox := Self;
  FStyle := csDropDown;
  FLastTime := 0;
  FAutoComplete := True;
  FAutoCloseUp := False;
  FAutoCompleteDelay := 500;
  FTextHint := '';
end;
Wenn du auf die Items zugreifst, dann gibt es schon eine Instanz.

Der Grund für diesen Setter liegt darin, dass in
Delphi-Quellcode:
TCustomCombo
die konkrete
Delphi-Quellcode:
TStrings
Instanz noch gar nicht bestimmt werden kann. Darum hat man den Setter so gebaut, dass die erste Verwendung die Referenz übernimmt.

Denn wenn du selber mal eine Komponente von
Delphi-Quellcode:
TCustomCombo
ableiten möchtest, dann hast du keine Möglichkeit an
Delphi-Quellcode:
FItems
heranzukommen und so bleibt dir der Weg über den Setter.
Delphi-Quellcode:
unit MyCompo;

interface

uses
  Vcl.StdCtrls;

type
  TMyCombo = class( TCustomCombo )
  public
    constructor Create( AOwner: TComponent ); override;
  end;

implementation

constructor TMyCombo.Create( AOwner: TComponent );
begin
  inherited Create( AOwner );
  SetItems( TStringList.Create ); // <- diese Instanz wird jetzt übernommen
end;

end.

uligerhardt 21. Aug 2015 07:57

AW: Lebensdauer einer Stringlist
 
Zitat:

Zitat von Sir Rufo (Beitrag 1312957)
Wenn du auf die Items zugreifst, dann gibt es schon eine Instanz.

Der Grund für diesen Setter liegt darin, dass in
Delphi-Quellcode:
TCustomCombo
die konkrete
Delphi-Quellcode:
TStrings
Instanz noch gar nicht bestimmt werden kann. Darum hat man den Setter so gebaut, dass die erste Verwendung die Referenz übernimmt.

Denn wenn du selber mal eine Komponente von
Delphi-Quellcode:
TCustomCombo
ableiten möchtest, dann hast du keine Möglichkeit an
Delphi-Quellcode:
FItems
heranzukommen und so bleibt dir der Weg über den Setter.

Das wäre aber mal einen Kommentar im Quelltext wert gewesen. Oder vielleicht sogar eine eigene Methode InitializeItems oder so.

idefix2 21. Aug 2015 10:09

AW: Lebensdauer einer Stringlist
 
Zitat:

Zitat von Sir Rufo (Beitrag 1312957)
Delphi-Quellcode:
constructor TMyCombo.Create( AOwner: TComponent );
begin
  inherited Create( AOwner );
  SetItems( TStringList.Create ); // <- diese Instanz wird jetzt übernommen
end;

end.

Die wird ja auch da nicht übernommen! im
Delphi-Quellcode:
inherited Create(AOwner)
wird die Instanz doch schon erzeugt, wenn du die Zuweisung machst, dann gibt es schon eine Instanz, und der Code würde ein Speicherleck produzieren, weil die neu erzeugte TSringlist in der Luft hängt.

Fazit - Das Ganze ist extrem unsauber und undurchsichtig gemacht, wobei mir der Nutzen völlig unklar ist.


Man müste das inherited create weglassen und alles selber machen. Oder zumindest die Instanz erzeugen, bevor man inherited create aufruft (wobei da vermutlich in der Folge auch irgendwas schiefgehen würde, habe ich das dumpfe Gefühl).


edit
Ich sehe gerade, du leitest diene Combobox von TCustomcombo und nicht von von TCustomcombobox ab - dann hast du Recht, das weist die Instanz zu.
Durchsichtig und verständlich ist die ganze Konstruktion aber nicht, und worin der Nutzen bestehen soll, sehe ich wirklich nicht.


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:56 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