Warum ensteht hier kein Memory Leak ?

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
danny61
Beiträge: 94
Registriert: So 5. Nov 2006, 18:40
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Berlin

Warum ensteht hier kein Memory Leak ?

Beitrag von danny61 »

Hallo,
ich habe in der letzten Zeit öfters so etwas hier gemacht :

ComboBox1.Items:=MyStringList1;

Bis mir dann eingefallen ist, das dann ja Memory Leaks entstehen, schließlich gibt es ja keinen Zeiger mehr auf die alte StringList von Combobox1.
Ich habe zum Test mal mit HeapTrc compiliert und siehe da es hagelte Fehler (wie unerwartet).
Daraufhin das ganze geändert :
ComboBox1.Items.Free;
ComboBox1.Items:=MyStringList1;

So weit alles in Ordnung.
An anderer Stelle mache ich dies hier:

Memo1.Lines:=MyStringList1;

Und egal wie oft ich dieses Konstrukt aufrufe, Heaptrc meldet keinen Fehler :o
Warum gibt es so kein Memory Leak ? Es gibt doch auch keinen Zeiger mehr auf die alte StringList des Memofeldes.
thx

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Re: Warum ensteht hier kein Memory Leak ?

Beitrag von theo »

Wieso machst Du's denn überhaupt so?

Mit

ComboBox1.Items.assign(MyStringList1);

ist doch alles in Butter.

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

Warscheinlich freet tmemo die strings automatisch bei neuzuweisung
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

Christian hat geschrieben:Warscheinlich freet tmemo die strings automatisch bei neuzuweisung


Moment mal.
Eigentlich geht das ja gar nicht unter mode objfpc.
ComboBox1.Items:=MyStringList1;

Das gemeinte (bzw in Delphi) wäre doch ComboBox1.Items:=@MyStringList1;
stimmts?

Und tatsächlich wird bei dem Statement ComboBox1.Items:=MyStringList1;
unter GTK die Funktion
procedure TGtkListStringList.Assign(Source : TPersistent);
aufgerufen!

Das ist also nicht wie bei Delphi!!!

Oder liege ich falsch?

danny61
Beiträge: 94
Registriert: So 5. Nov 2006, 18:40
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Berlin

Beitrag von danny61 »

@Theo
weil ich Assign für TStringlist übersehen hatte :oops:

danny61
Beiträge: 94
Registriert: So 5. Nov 2006, 18:40
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Berlin

Beitrag von danny61 »

Der Quellcode von TustomMemo sieht wie erwartet so aus :

procedure TCustomMemo.SetLines(const Value : TStrings);
begin
if (Value <> nil) then
FLines.Assign(Value);
end;

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

danny61 hat geschrieben:@Theo
weil ich Assign für TStringlist übersehen hatte :oops:


Aber wenn das stimmt was ich oben geschrieben habe, dann hast du doch ein Assign gemacht, ohne es zu wissen ;-)
Hast du $mode objfpc oder $mode delphi ?

Kann da jemand was dazu sagen.

danny61
Beiträge: 94
Registriert: So 5. Nov 2006, 18:40
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Berlin

Beitrag von danny61 »

Ich habe $mode objfpc
Bei der ComboBox sieht der Quellcode ähnlich aus:

procedure TCustomComboBox.SetItems(Value : TStrings);
begin
if (Value <> FItems) then begin
FItems.Assign(Value);
end;
end;

Dann ist allerdings die Frage: Warum kam es dort zu Memory Leaks ?

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

Die kommen warscheinlich daher das du die anderen Stringlists nicht freigegeben hast.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

danny61
Beiträge: 94
Registriert: So 5. Nov 2006, 18:40
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Berlin

Beitrag von danny61 »

Tja,

ComboBox1.Items.Assign(MyStringList);

reicht eben doch nicht.
Auch so habe ich Memory Leaks. Nur mit

ComboBox1.Items.Free;
ComboBox1.Items.Assign(MyStringList);

funktioniert es.
Womit ich wieder bei der Frage wäre : Warum treten bei

Memo1.Lines:=MyStringList;

keine Memory Leaks auf ?

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

danny61 hat geschrieben:Womit ich wieder bei der Frage wäre : Warum treten bei
Memo1.Lines:=MyStringList;
keine Memory Leaks auf ?


Keine Ahnung. Hast Du denn MyStringList auch beide male freigegeben?

Um die Verwirrung von vorhin noch zu klären:

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var SL1,SL2:TStrings;
begin
SL1:=TStringList.create;
Memo1.lines:=SL1;  //Property von TMemo, wird implizit Assigned
SL1.Free;
Memo1.Lines.add('Klappt');
 
SL1:=TStringList.create;
SL2:=TStringList.create;
SL2:=SL1; //Scheint nur den Pointer zu setzen
SL1.free;
SL2.add('Zugriffsverletzung');
end;

danny61
Beiträge: 94
Registriert: So 5. Nov 2006, 18:40
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Berlin

Beitrag von danny61 »

Ich habe zunächst gar nichts freigegeben.
Dadurch kam es zu den Leaks bei der ComboBox aber eben nicht im Memo.

Das Verhalten deiner Prozedur ist mir auch nicht so ganz klar.
Warum kannst du über Memo.Lines.Add etwas zu der StringList hinzufügen, wenn du sie vorher freigegeben hast ?

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

Memo1.lines:=SL1;

ist in diesem Fall das selbe wie Memo1.Lines.Assign(SL1);

deshalb kann er dei SL1 danach freigeben und zum memo eine zeile hinzufügen

in deinem beispiel heisst das deine memoryleaks treten auf weil du die Stringlist nicht freigibst hinterher
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

Christian hat geschrieben:Memo1.lines:=SL1;
ist in diesem Fall das selbe wie Memo1.Lines.Assign(SL1);


Genau! Das soll der obige Code zeigen.

Im Fall von TMemo (und anderen) ist Lines ein property.
Die Zuweisung von TStrings an Lines wird über die Procedur SetLines abgewickelt:

procedure TCustomMemo.SetLines(const Value : TStrings);
begin
if (Value <> nil) then
FLines.Assign(Value);
end;

Also es wird eine Kopie des Inhalts gemacht. Beide TStrings sind immer noch da.

Im Fall von SL1:=SL2 wird aber nur der Pointer gleichgesetzt.
D.h. Der Zugriff auf SL1 geht flöten und SL1 zeigt auf das gleiche wie SL2.

Also aufgepasst! ;-)

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

Was ich allerdings immer noch nicht kapiere:
Warum kompiliert SL1:=SL2 im mode objfpc überhaupt?
Ich dachte immer das wäre zwinged SL1:=@SL2

Aber SL1:=@SL2 kompiliert gar nicht:
Error: Incompatible types: got "Pointer" expected "TStrings"
Das hingegen ist Delphi wieder egal.

??? Ich steh auf dem Schlauch....

Antworten