Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Nur free oder FreeandNil (https://www.delphipraxis.net/25017-nur-free-oder-freeandnil.html)

Helmi 29. Jun 2004 21:40


Nur free oder FreeandNil
 
Hallo,

ich hab grad einen thread durchgelesen und da wurde eine stringlist in dem Event "OnDestroy" mit freeAndNil freigegeben

ich wollte mal fragen was ist besser:

Code:
procedure TForm1.FormDestroy(Sender: TObject);
begin
  FreeAndNil(sl);
end;
oder

Code:
procedure TForm1.FormDestroy(Sender: TObject);
begin
  sl.free;
end;
mfg
Helmi

neolithos 29. Jun 2004 21:45

Re: Nur free oder FreeandNil
 
FreeAndNil setzt die Variable noch auf nil, diesen Mehraufwand sollte man hinsichtlich der Fehlersuche vorziehen.

Free tut dies nicht, ist deshalb ein paar Takte schneller, was man aber nicht großartig merkt.

SirThornberry 29. Jun 2004 21:48

Re: Nur free oder FreeandNil
 
Najs, wirklich besser ist keins von beiden. Es kommt drauf an was dir besser gefällt. Bei "Free" wird einfach der speicher freigegeben und das Object zerstört. Bei "FreeAndNil" wird das Objectauch freigegeben und der zeiger auf nil gesetzt. Im Normalfall reicht ein einfaches Free.

Wenn du nach dem freigeben der pointer nicht auf "nil" gesetzt wird ist es nicht so leicht heruaszufinden ob das Object bereits freigegeben wurde. Wenn du allerdings vorher FreeAndNil aufrufst kanns du später mit "Object = nil" überprüfen ob das Object bereits frei gegeben wurde

Helmi 29. Jun 2004 21:48

Re: Nur free oder FreeandNil
 
und was sollte mann jetzt generell machen?
so als profitip??

Luckie 29. Jun 2004 21:53

Re: Nur free oder FreeandNil
 
FreeAndNil.

@Sir T.: Du bist ja auch lustig. ;)
Zitat:

Najs, wirklich besser ist keins von beiden.
Und dann im zweiten Absatzt schreibst du praktisch ein Pro für FreeAndNil. :mrgreen:

neolithos 29. Jun 2004 21:54

Re: Nur free oder FreeandNil
 
Ich benutze meist FreeAndNil, da ich so schnell Fehler, durch zu früh freigegebene Objecte erkennen kann.

--> "Zugriff auf Adresse (nahe 0) konnte nicht ausgeführt."

Uncle Cracker 29. Jun 2004 21:58

Re: Nur free oder FreeandNil
 
Und was muss ich machen unter Delphi 4? Da reicht doch auch ein normales Free oder muss ich da sonst noch was anderes machen?

PS: Unter Delphi 4 gibt es kein FreeAndNil (bzw. ich bin wirklich so doof das ich es nicht finde :roll: :gruebel: :stupid: )

Luckie 29. Jun 2004 22:05

Re: Nur free oder FreeandNil
 
Delphi-Quellcode:
sl.Free;
sl := nil;
Oder
Delphi-Quellcode:
procedure D4FreeAndNil(Object: TObject);
begin
  Object.Free;
  Object := nil;
end;
Es verhält sich so: Free entfernt nur das Objekt aus dem Speicher, die Objektvariable beinhaltet abr noch eine "gültige" Zeiger-Adresse, die aber nach dem Free je doch auf einen ungültigen Speicherbereich verweist. Da die Objektvariable immer noch einen gültigen Zeiger beinhaltet liefert ein Test mit Assigned auch nach einem Free noch True zurück. FreeAndNil setzt die Objektvariable eben noch zurück - auf nil eben, wie der Prozedurname schon vermuten läßt.

phXql 29. Jun 2004 22:26

Re: Nur free oder FreeandNil
 
wenn ich ein object nur .free'e, wie kann ich dann prüfen, ob das objekt noch da is oder nich?

Luckie 29. Jun 2004 22:28

Re: Nur free oder FreeandNil
 
Gar nicht. Bzw. du greifst drauf zu und wenn es kracht, gab es das Objekt nicht mehr. Deswegen habe ich mir angewöhnt FreeAndNil zu benutzen auch wenn ich Objekte im OnDestroy Event der Form freigebe.

NicoDE 30. Jun 2004 00:23

Re: Nur free oder FreeandNil
 
Zitat:

Zitat von Luckie
Oder
[...]

Da fehlte ein var und der Zeiger sollte vor dem Freigeben gesetzt werden (trotzdem wäre bei SMP-Systemen ein Lock nicht überflüssig...)
Delphi-Quellcode:
procedure FreeAndNil(var Obj);
var
  Temp: TObject;
begin
  Temp := TObject(Obj);
  Pointer(Obj) := nil;
  Temp.Free;
end;

Christian Seehase 30. Jun 2004 00:31

Re: Nur free oder FreeandNil
 
Moin Luckie,

wenn, dann aber

Code:
procedure D4FreeAndNil([color=red][b]var[/b][/color] Obj: TObject);
begin
  Obj.Free;
  Obj := nil;
end;
ohne das var davor wird der Wert von Obj nicht auf nil gesetzt. ;-)

Luckie 30. Jun 2004 00:35

Re: Nur free oder FreeandNil
 
Zitat:

Zitat von NicoDE
Da fehlte ein var und der Zeiger sollte vor dem Freigeben gesetzt werden (trotzdem wäre bei SMP-Systemen ein Lock nicht überflüssig...)
Delphi-Quellcode:
procedure FreeAndNil(var Obj);
var
  Temp: TObject;
begin
  Temp := TObject(Obj);
  Pointer(Obj) := nil;
  Temp.Free;
end;

Überredet. ;)

Christian Seehase 30. Jun 2004 00:37

Re: Nur free oder FreeandNil
 
Moin Nico,

Zitat:

Zitat von NicoDE
...und der Zeiger sollte vor dem Freigeben gesetzt werden...

OK, aber warum?

NicoDE 30. Jun 2004 00:56

Re: Nur free oder FreeandNil
 
Zitat:

Zitat von Christian Seehase
OK, aber warum?

Eigentlich gibt es - was SysUtils.FreeAndNil angeht - keinen echten Grund dafür, da Temp ohnehin nicht validiert wird (deswegen 'sollte'...).
Dem Benutzer muss klar sein, dass eine doppelte Freigabe nicht möglich ist.

Eine eigene Funktion im Stile von...
Delphi-Quellcode:
procedure MyFreeAndNil(var Obj);
var
  Temp: TObject;
begin
{$IFDEF WIN32}
  Temp := TObject(InterlockedExchange(Integer(Obj), Integer(nil)));
  if Temp <> nil then
    Temp.Free;
{$ELSE}
  Temp := TObject(Obj);
  Pointer(Obj) := nil;
  if Temp <> nil then
    Temp.Free;
{$ENDIF}
end;
...kann in MT-Scenarien durchaus hilfreich sein.

Ist aber alles eine Frage des Kontextes in dem man die Funktion verwenden möchte. SysUtils.FreeAndNil hat den Vorteil, dass man doppelte Freigaben schneller bemerkt. Die oben skizzierte Version hat ihre Vorteile bei der einfacheren Handhabung von Objekten, welche von mehreren Threads verwendet werden (und auch nur dann, wenn man selbst kein Locking für die Freigabe implementiert hat, bzw. implementieren will - insofern bleibt die Nützlichkeit von MyFreeAndNil fragwürdig...).


Gruss Nico

Robert Marquardt 30. Jun 2004 05:24

Re: Nur free oder FreeandNil
 
FreeAndNil ist wirklich eine interessante Funktion.
Luckie zeigt die Borland-Implementation. Die kann lustige Nebenwirkungen haben, da innerhalb des Free auf die bereits zu nil gesetzte Variable gegriffen werden kann. In dem Fall bleibt nur die Seehase-Methode.
Generell sollte man FreeAndNil immer anwenden, ausser an performance-relevanten Stellen. Das ist aber ausgesprochen selten.

Bei der JVCL habe ich z. B. mal die finalization-Sections entsprechend aufgearbeitet und danach stuerzte Delphi nicht mehr ab wenn man alle Pakete neu uebersetzte.

Nicodius 30. Jun 2004 05:28

Re: Nur free oder FreeandNil
 
ich denke ein normales free tuts in den meisten fällen(*mirwiederfeindemach* ;) )...

Robert Marquardt 30. Jun 2004 05:37

Re: Nur free oder FreeandNil
 
Bei kleinen Projekten ja, aber bei grossen mit mehreren Programmierern ist FreeAndNil sehr hilfreich.

Phoenix 30. Jun 2004 07:31

Re: Nur free oder FreeandNil
 
Also wenn ich Objekte nur innerhalb von Funktionen verwende, nehme ich free, wenn ich das Objekt später in der Funktion nicht mehr verwende (will heissen im finally - Block am Ende, wo die Funktion eh endet).

EInfach aus den Grund: Nach dem Ende der Funktion gibt es die Variablen eh nicht mehr. Dann brauch ich sie nicht auf nil setzen wenn sie eh weggeworfen wird.

Anders ist das bei Member-Variablen meiner Objekte. Diese gebe ich immer mit FreeAndNil frei (ausser im Destruktor, danach gibts das Objekt ja auch nicht mehr).

Will heissen: Genau dann, wenn ich nach der Freigabe gar nicht mehr auf die Referenz zugreifen kann, verwende ich Free, in allen anderen Fällen FreeAndNil.

Helmi 30. Jun 2004 09:13

Re: Nur free oder FreeandNil
 
hallo,

es ist interessant, was eine kleine Frage auslösen kann :-D

aber ich dank euch trotzdem für die ganzen Kommentare...

:-D :-D

mfg
Helmi

:thuimb:

Muetze1 30. Jun 2004 10:22

Re: Nur free oder FreeandNil
 
Moin!

Zitat:

Zitat von Christian Seehase
Moin Nico,

Zitat:

Zitat von NicoDE
...und der Zeiger sollte vor dem Freigeben gesetzt werden...

OK, aber warum?

Folgendes Szenario: Du willst ein Objekt freigeben und es kann sein, das dies nicht ordentlich existiert. Würdest du erst das Free aurufen und dann das Nil, dann würde er beim Free mit einer Exception aussteigen und der Objektzeiger wird nicht mehr auf Nil gesetzt - und es geschieht vielleicht nochmal das gleiche - und immer wieder. Daher erst auf Nil setzen, dann kommt man nicht nochmal auf die Idee...

MfG
Muetze1

Luckie 30. Jun 2004 11:03

Re: Nur free oder FreeandNil
 
Zitat:

Zitat von Muetze1
Du willst ein Objekt freigeben und es kann sein, das dies nicht ordentlich existiert. Würdest du erst das Free aurufen und dann das Nil, dann würde er beim Free mit einer Exception aussteigen

Nein würde er nicht. Free prüft erst, ob das Objekt existiert und ruft dann den Destruktor auf. Deswegen soll man den Destroktor (Destroy) auch nie direkt aufrufen. Aus der Hilfe:
Zitat:

Free automatically calls the destructor if the object reference is not nil.

Muetze1 30. Jun 2004 11:42

Re: Nur free oder FreeandNil
 
Moin Luckie!

So meinte ich das nicht. Ich bin von dem Fall ausgegangen das in dem Instanzenzeiger irgendeine Adresse drinne steht - nicht nil - die beim Free dadurch zu einer Exception führt. Diese würde dann abgefangen werden und bei FreeAndNil() wäre der Instanzenzeiger dann Nil, bei einem Free; und dann einem := Nil, würde er nicht mehr zum := Nil kommen und daher ...

Ich bin nicht vom Idealfall ausgegangen, das der Instanzenzeiger einen Nil Wert enthält.

MfG
Muetze1


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:18 Uhr.

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