Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi ComboBox mit unterschiedlichen Objekten - sauber abraeumen? (https://www.delphipraxis.net/87088-combobox-mit-unterschiedlichen-objekten-sauber-abraeumen.html)

OldGrumpy 23. Feb 2007 07:39


ComboBox mit unterschiedlichen Objekten - sauber abraeumen?
 
Hallo zusammen,

ich hab mal wieder ein übles Stückchen Software vor mir. Momentan habe ich da eine Combobox, der mittels AddObject() neben den einzelnen Strings auch unterschiedliche zugehörige Objekte (fragt mich nicht warum, dazu komme ich erst später, erstmal muss ich die drei Millionen Speicherlecks beheben...) zugewiesen werden. Wenn die Combobox später abgeräumt wird, muss ich natürlich diese Objekte auch einzeln wieder freigeben, nur wie komme ich da ran? Entweder bin ich zu doof die OH zu verstehen oder ich seh den Wald vor lauter Bäumen nicht. Bei meinen bisherigen Experimenten bin ich noch nicht über diverse Access Violations hinausgekommen... Auch die Suche hier im Forum war nicht wirklich erleuchtend, kann mir mal jemand bitte einen Schubs in die richtige Richtung geben? :) Herzlichen Dank schonmal im Voraus :mrgreen:

mkinzler 23. Feb 2007 07:41

Re: ComboBox mit unterschiedlichen Objekten - sauber abraeum
 
.Objects

OldGrumpy 23. Feb 2007 07:49

Re: ComboBox mit unterschiedlichen Objekten - sauber abraeum
 
okay, ich haette dazusagen sollen, dass ein myCombobox.Items.Objects[i].Free zu den erwähnten AVs führt.

IngoD7 23. Feb 2007 07:56

Re: ComboBox mit unterschiedlichen Objekten - sauber abraeum
 
Zitat:

Zitat von OldGrumpy
okay, ich haette dazusagen sollen, dass ein myCombobox.Items.Objects[i].Free zu den erwähnten AVs führt.

Wie und wo machst du es denn (Code)?

OldGrumpy 23. Feb 2007 08:18

Re: ComboBox mit unterschiedlichen Objekten - sauber abraeum
 
Wo ist mein Kaffee... bin noch nicht ganz wach, das Projekt das ich hier übernommen hab ist echt schlimm. Ich hab in den letzten Tagen sicherlich fuenfhundertmal TList.Create gesehen, gefolgt von diversen Zuweisungen von Objekten in die Liste und danach ein einfaches TList.Free - ohne vorher die Objekte abzuraeumen. Das Logfile von FastMM4 war 1,9 MB gross :shock: und inzwischen bin ich auf 450kb runter ;)

Also, befüllt wird die Combobox in MyForm.FormCreate (gebunden ans OnCreate-Event):

Delphi-Quellcode:
procedure TMyForm.FormCreate(Sender: TObject);
Begin
[...]
MyComboBox.items.addObject(menutext, TObject(integer(TMyEffect)));
MyComboBox.items.addObject(menutext2, TObject(integer(TMyEffect2)));
[...]
End;
menutext und menutext2 sind Strings, und wo ichs jetzt paste wundere ich mich, was das mit dem TMyEffect usw. soll - TMyEffect und Konsorten sind Klassendefinitionen.

Abgeraeumt soll das ganze natürlich in TMyForm.FormDestroy (gebunden ans OnDestroy-Event):

Delphi-Quellcode:
procedure TMyForm.FormDestroy(Sender: TObject);
var i: integer;
Begin
[...]
for i:=0 to MyComboBox.Items.Count-1 do MyComboBox.Items.Objects[i].Free;
[...]
End;
So, und nun bin ich mal gespannt, was ich da übersehen hab :)

mkinzler 23. Feb 2007 08:19

Re: ComboBox mit unterschiedlichen Objekten - sauber abraeum
 
Zitat:

Delphi-Quellcode:
MyComboBox.items.addObject(menutext, TObject(integer(TMyEffect)));

?

ste_ett 23. Feb 2007 08:20

Re: ComboBox mit unterschiedlichen Objekten - sauber abraeum
 
Hast du auf "<> nil" geprüft? :)

OldGrumpy 23. Feb 2007 08:27

Re: ComboBox mit unterschiedlichen Objekten - sauber abraeum
 
Zitat:

Zitat von ste_ett
Hast du auf "<> nil" geprüft? :)

Ja, nirgends nil zu sehen. Würde mich auch wundern wenn nach der obigen Zuweisung irgendwo nil drinständ ;)

Zitat:

Zitat von mkinzler
Zitat:

Delphi-Quellcode:
MyComboBox.items.addObject(menutext, TObject(integer(TMyEffect)));

?

Könntest Du bitte im ganzen Satz fragen? Ist noch früh :)

mkinzler 23. Feb 2007 08:32

Re: ComboBox mit unterschiedlichen Objekten - sauber abraeum
 
Warum versuchst du eine Referenz(Zeiger) auf ein Objekt zuerst in einene Integer und dann in ein TObject zu casten (jedes Objekt ist schon ein TObject) ?

OldGrumpy 23. Feb 2007 08:35

Re: ComboBox mit unterschiedlichen Objekten - sauber abraeum
 
Zitat:

Zitat von mkinzler
Warum versuchst du eine Referenz(Zeiger) auf ein Objekt zuerst in einene Integer und dann in ein TObject zu casten (jedes Objekt ist schon ein TObject) ?

Das ist nicht mein Code, ich hab das Projekt nur übernommen nachdem der alte Programmierer das Weite gesucht hat ;) Das ganze Paket hat weit über hunderttausend Zeilen Code, ich hab in den drei Tagen jetzt noch nicht allzuviel davon wirklich anschauen können. Was das da soll, kann ich Dir auf Anhieb auch nicht sagen, ich schau mal eben ob sich da was finden lässt das Aufschluss gibt...

raiguen 23. Feb 2007 09:14

Re: ComboBox mit unterschiedlichen Objekten - sauber abraeum
 
Zitat:

Zitat von OldGrumpy
Abgeraeumt soll das ganze natürlich in TMyForm.FormDestroy (gebunden ans OnDestroy-Event):

Delphi-Quellcode:
procedure TMyForm.FormDestroy(Sender: TObject);
var i: integer;
Begin
[...]
for i:=0 to MyComboBox.Items.Count-1 do MyComboBox.Items.Objects[i].Free;
[...]
End;
So, und nun bin ich mal gespannt, was ich da übersehen hab :)

Nur ne Kleinigkeit ( das wurde aber bereits schon erwähn): vor dem Freigeben des Objekts ist keine Prüfung auf nil oder Assigned; d.h. bei einem nicht vorhandenen Objekt kann das Free durchaus ne AV produzieren ;)
Angepasster Cdode:
Delphi-Quellcode:
for i:= MyComboBox.Items.Count-1 downto 0 do
  if Assigned(MyComboBox.Items.Objects[i]) then
    MyComboBox.Items.Objects[i].Free;

OldGrumpy 23. Feb 2007 09:27

Re: ComboBox mit unterschiedlichen Objekten - sauber abraeum
 
Zitat:

Zitat von raiguen
Nur ne Kleinigkeit ( das wurde aber bereits schon erwähn): vor dem Freigeben des Objekts ist keine Prüfung auf nil oder Assigned; d.h. bei einem nicht vorhandenen Objekt kann das Free durchaus ne AV produzieren ;)

Danke raiguen,

aber zum einen wurde jedem Item ein Objekt zugewiesen, und zum anderen habe ich gerade mal mit dem Debugger geschaut, da ist kein einziges Nil dabei. Die AV gibts trotzdem...

Nachtrag:

Im OnClick-Event (???) gibts dann folgenden Code:
Delphi-Quellcode:
procedure MyForm.MyComboBoxClick(Sender: TObject);
var e: TSingleEffect;
    i: integer;
begin
  i:= MyComboBox.itemindex;
  if assigned(nochEineListe) and (i>=0) and (i<MyComboBox.items.count) then
  begin
    e:= TSingleEffectClass(MyComboBox.Items.objects[i]).create(nochEineListe);
    nochEineListe.addeffect(e);
  end;
end;
Da setzt es bei mir dann wirklich langsam aus :mrgreen:

Achja, das fehlt noch:

Delphi-Quellcode:
type
  TSingleEffect= class(TPanelEffect)
  [...]
  end;
  TSingleEffectClass= class of TSingleEffect;
Kommt das nur mir ziemlich wurstig vor? :gruebel:

IngoD7 23. Feb 2007 09:50

Re: ComboBox mit unterschiedlichen Objekten - sauber abraeum
 
Von welchem Typ ist eigentlich MyComboBox? TComboBox oder etwas selbstgeschriebenes?

marabu 23. Feb 2007 10:12

Re: ComboBox mit unterschiedlichen Objekten - sauber abraeum
 
Hallo,

Delphi-Quellcode:
procedure TMyForm.FormCreate(Sender: TObject);
Begin
[...]
  MyComboBox.items.addObject(menutext, TObject(integer(TMyEffect)));
  MyComboBox.items.addObject(menutext2, TObject(integer(TMyEffect2)));
[...]
End;
wenn sich der "flüchtige" Kollege ein wenig an die Namenskonvention gehalten hat, dann werden hier keine Objekte, sonder Klassenreferenzen angehängt. Die sollten dann aber nicht freigegeben werden...

Freundliche Grüße

OldGrumpy 23. Feb 2007 10:28

Re: ComboBox mit unterschiedlichen Objekten - sauber abraeum
 
Zitat:

Zitat von IngoD7
Von welchem Typ ist eigentlich MyComboBox? TComboBox oder etwas selbstgeschriebenes?

Weder noch, TTntComboBox - die ComboBox aus den TNTWare Unicode Controls.

Zitat:

Zitat von marabu
wenn sich der "flüchtige" Kollege ein wenig an die Namenskonvention gehalten hat, dann werden hier keine Objekte, sonder Klassenreferenzen angehängt. Die sollten dann aber nicht freigegeben werden...

Freundliche Grüße

Ich habe aber auf jeden Fall Memoryleaks die aus dem AddObject resultieren, und die sind zu gross als dass es einfach nur Pointer sein könnten. Dieses Projekt ist echt der Wahnsinn... Der Editor ist zum Beispiel keine "echte" grafische Komponente mit eigenen Controls, sondern der wird vom Mainform aus mit den Controls die auf dem Mainform liegen "verdrahtet". Macht sowas Sinn? :gruebel: Gibt auf jeden Fall derbe Probleme beim korrekten Abräumen da immer wieder die Frage auftaucht "wem gehört dies oder jenes, und wer raeumt es ab"...

IngoD7 23. Feb 2007 10:33

Re: ComboBox mit unterschiedlichen Objekten - sauber abraeum
 
Zitat:

Zitat von marabu
Hallo,

Delphi-Quellcode:
procedure TMyForm.FormCreate(Sender: TObject);
Begin
[...]
  MyComboBox.items.addObject(menutext, TObject(integer(TMyEffect)));
  MyComboBox.items.addObject(menutext2, TObject(integer(TMyEffect2)));
[...]
End;
wenn sich der "flüchtige" Kollege ein wenig an die Namenskonvention gehalten hat, dann werden hier keine Objekte, sonder Klassenreferenzen angehängt. Die sollten dann aber nicht freigegeben werden...

Naja, TComboBox.Items.Objects[] enthält immer nur Referenzen. Die Frage ist, ob diese Referenz auf ein real existierendes Objekt zeigt, das man auch freigeben könnte. Das scheint hier eben nicht der Fall zu sein.

Ich weiß auch gar nicht, welche Zahl das ist, wenn man eine Klasse auf Integer castet. Was kann man mit der Zahl anfangen? Was hat man davon, diese Zahl (also den Integer) dann auf TObject zu casten und den Zeiger dann in eine Objektliste zu hängen? :gruebel:

IngoD7 23. Feb 2007 10:51

Re: ComboBox mit unterschiedlichen Objekten - sauber abraeum
 
Zitat:

Zitat von OldGrumpy
Zitat:

Zitat von IngoD7
Von welchem Typ ist eigentlich MyComboBox? TComboBox oder etwas selbstgeschriebenes?

Weder noch, TTntComboBox - die ComboBox aus den TNTWare Unicode Controls.

Die kenne ich nicht. Wer weiß, was die alles in AddObjects anstellt.

Zitat:

Zitat von OldGrumpy
Ich habe aber auf jeden Fall Memoryleaks die aus dem AddObject resultieren, und die sind zu gross als dass es einfach nur Pointer sein könnten.

Die Aussage würde ich dir bei TComboBox nicht abnehmen, weil in ihr nur Zeiger gehalten werden, die sich mit dem Freigeben einer Box vom Typ TComboBox erledigen. Da aber eine andere ComboBox-Klasse verwendet wird, wird man (du) wohl diese erstmal analysieren müssen.

marabu 23. Feb 2007 11:07

Re: ComboBox mit unterschiedlichen Objekten - sauber abraeum
 
Hallo Ingo,

Zitat:

Zitat von IngoD7
... Naja, TComboBox.Items.Objects[] enthält immer nur Referenzen. Die Frage ist, ob diese Referenz auf ein real existierendes Objekt zeigt, das man auch freigeben könnte. Das scheint hier eben nicht der Fall zu sein. ...

Klassenreferenz ist in Object Pascal ein terminus technicus, die Online Hilfe enthält dazu sicher ein Kapitel. Klassen werden nicht freigegeben, Free ist auch keine class method.

Zitat:

Zitat von IngoD7
... Ich weiß auch gar nicht, welche Zahl das ist, wenn man eine Klasse auf Integer castet. Was kann man mit der Zahl anfangen? Was hat man davon, diese Zahl (also den Integer) dann auf TObject zu casten und den Zeiger dann in eine Objektliste zu hängen? ...

Im vorliegenden Fall ist TObject(Integer(TMyEffect)) identisch mit TMyEffect - zuletzt ist alles ein Zeiger in unterschiedlichen Interpretationen. Durch die in Objects[] hinterlegte Klasse kann bei Auswahl eines Items der ComboBox die entsprechende Klasse instanziert werden.

Freundliche Grüße

IngoD7 23. Feb 2007 11:53

Re: ComboBox mit unterschiedlichen Objekten - sauber abraeum
 
Hi marabu,
danke für die Erklärung! :thumb:

Zitat:

Zitat von marabu
Hallo Ingo,
Zitat:

Zitat von IngoD7
... Naja, TComboBox.Items.Objects[] enthält immer nur Referenzen. Die Frage ist, ob diese Referenz auf ein real existierendes Objekt zeigt, das man auch freigeben könnte. Das scheint hier eben nicht der Fall zu sein. ...

Klassenreferenz ist in Object Pascal ein terminus technicus, die Online Hilfe enthält dazu sicher ein Kapitel. Klassen werden nicht freigegeben, Free ist auch keine class method.

So weit, so (auch schon vorher) klar. Letztlich wollte ich genau das auch nur bestätigen/ergänzen. (Auch wenn ich lange nicht alles zum Thema Klassenreferenzen und Klassenmethoden verstanden habe, was ich jemals drüber gelesen habe. :| )

Viel spannender ist da folgendes:
Zitat:

Zitat von marabu
Zitat:

Zitat von IngoD7
... Ich weiß auch gar nicht, welche Zahl das ist, wenn man eine Klasse auf Integer castet. Was kann man mit der Zahl anfangen? Was hat man davon, diese Zahl (also den Integer) dann auf TObject zu casten und den Zeiger dann in eine Objektliste zu hängen? ...

Im vorliegenden Fall ist TObject(Integer(TMyEffect)) identisch mit TMyEffect - zuletzt ist alles ein Zeiger in unterschiedlichen Interpretationen. Durch die in Objects[] hinterlegte Klasse kann bei Auswahl eines Items der ComboBox die entsprechende Klasse instanziert werden.

:shock: Sowas in der Art?
Delphi-Quellcode:
var
   ObjVar: TObject;
begin
   ObjVar := MyComboBox.Items.Objects[MyComboBox.ItemIndex].Create;
end;
Das klappt doch nicht, oder? :gruebel:

OldGrumpy 23. Feb 2007 12:00

Re: ComboBox mit unterschiedlichen Objekten - sauber abraeum
 
Zitat:

Zitat von "IngoD7
Zitat:

Zitat von OldGrumpy
Ich habe aber auf jeden Fall Memoryleaks die aus dem AddObject resultieren, und die sind zu gross als dass es einfach nur Pointer sein könnten.

Die Aussage würde ich dir bei TComboBox nicht abnehmen, weil in ihr nur Zeiger gehalten werden, die sich mit dem Freigeben einer Box vom Typ TComboBox erledigen. Da aber eine andere ComboBox-Klasse verwendet wird, wird man (du) wohl diese erstmal analysieren müssen.

Diese Memoryleaks habe ich auch nach testweiser Umstellung auf TComboBox weiterhin. Ich begreif den Mechanismus dahinter auch nicht, ich sehe nur am Stacktrace von FastMM4 was da passiert - und der letzte Call daraus ist halt das AddObject() - die Calls danach sind mir klar. Also wird da aus welchen Gründen auch immer Speicher belegt den ich nicht wieder freigeben kann *grmpf*

marabu 23. Feb 2007 12:05

Re: ComboBox mit unterschiedlichen Objekten - sauber abraeum
 
Hi Ingo,

besser so:

Delphi-Quellcode:
procedure TDemoForm.FormCreate(Sender: TObject);
begin
  with ComboBox.Items do
    AddObject('demo', TObject(TStringList));
end;

procedure TDemoForm.ButtonClick(Sender: TObject);
var
  s: TStrings;
begin
  with ComboBox.Items do
    s := TClass(Objects[0]).Create as TStrings;
  s.Add('Ingo');
  s.Free;
end;
Bei deinem Create würde, wenn denn ein "echtes" Objekt gespeichert wäre, dieses mit Create() lediglich auf den Ausgangszustand zurück gesetzt. Du musst den richtigen TypeCast einsetzen.

Freundliche Grüße

IngoD7 23. Feb 2007 12:31

Re: ComboBox mit unterschiedlichen Objekten - sauber abraeum
 
Zitat:

Zitat von marabu
Bei deinem Create würde, wenn denn ein "echtes" Objekt gespeichert wäre, dieses mit Create() lediglich auf den Ausgangszustand zurück gesetzt. Du musst den richtigen TypeCast einsetzen.

Mein Create (und nicht nur in der Variation, wie ich es angegeben hatte) funktionierte gar nicht!
Ich hatte TClass(..) as .. völlig unterschlagen, wohl weil ich solche Konstrukte noch nie verwenden musste. So geht's jedenfalls. Danke.

Back to Topic:
Damit ist aber auch noch nicht geklärt, wieso (angeblich) das AddObject (im "Problemcode" hier im Thread) Speicher verbrät.

marabu 23. Feb 2007 13:31

Re: ComboBox mit unterschiedlichen Objekten - sauber abraeum
 
Hallo OldGrumpy,

Zitat:

Zitat von OldGrumpy
... Ich habe aber auf jeden Fall Memoryleaks die aus dem AddObject resultieren, und die sind zu gross als dass es einfach nur Pointer sein könnten. ...

ich kenne nur die eine Stelle aus deinem Code, zu der ich meinen Kommentar abgegeben habe, und dort sollte kein Speicher verloren gehen. Du kannst das leicht überprüfen, indem du eine Testanwendung aufmachst und in der nur mein Code-Beispiel verwendest. Wenn dort keine Speicherverluste auftreten, dann müssen wir den Fehler woanders suchen. Tritt er dort auch auf, dann finden wir sicher auch eine Erklärung. Teste mal, während ich meinen Stellungswechsel vollziehe.

Zitat:

Zitat von OldGrumpy
... Der Editor ist zum Beispiel keine "echte" grafische Komponente mit eigenen Controls, sondern der wird vom Mainform aus mit den Controls die auf dem Mainform liegen "verdrahtet". Macht sowas Sinn? ...

Das ist zu ungenau, als dass ich es kommentieren könnte.

Freundliche Grüße


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