Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Freigeben einer Pointerstruktur (https://www.delphipraxis.net/135659-freigeben-einer-pointerstruktur.html)

Hybrid666 15. Jun 2009 15:20


Freigeben einer Pointerstruktur
 
Hi,

ich muss sagen das ist das erste mal das ich großartig mit Zeigern in Delphi arbeite, darum auch hier gleich eine Frage, zu der ich nach langem suchen auch keine antwort habe.

Ich habe die Folgende Pointerstruktur:
Delphi-Quellcode:
  PCommands = ^TCommands;
  TCommands = record
    KeyInput : Boolean;
    Input : TInputType;
    Parameter : String;
    Next : PCommands;
  end;

  PMakro = ^TMakro;
  TMakro = record
    TimeStamp : Integer;
    Commands : PCommands;
    Next : PMakro;
  end;
und habe auf einen Button eine ganz kleine Teststruktur angelegt:
Delphi-Quellcode:
procedure TForm1.Button4Click(Sender: TObject);
var
  Anchor : PMakro;
begin
  new (Anchor);
  Anchor^.TimeStamp := 10;
  new (Anchor^.Commands);
  Anchor^.Commands^.KeyInput := True;
  FreeMakro (Anchor);
end;
und wollte testen, ob meine Freigabefunktionen funktionieren, sie arbeiten rekursiv und sollen eigentlich die listen von hinten nach vorne zerstören:

Delphi-Quellcode:
procedure TForm1.FreeMakro (Anchor : PMakro);
begin
  if Assigned (Anchor) then
  begin
    if Assigned (Anchor.Commands) then FreeCommands (Anchor.Commands);
    if Assigned (Anchor.Next) then FreeMakro (Anchor.Next);
    dispose (Anchor);
  end;
end;

procedure TForm1.FreeCommands (Anchor : PCommands);
begin
  if Assigned (Anchor) then
  begin
    if Assigned (Anchor.Next) then FreeCommands (Anchor^.Next); //  <---- HIER WIRD EINE AV AUSGELÖST
    dispose (Anchor);
  end;
end;
ich hab markiert wo ich eine AV bekomme, kann mir einer sagen was ich falsch gemacht habe?

Danke schonmal

MfG Hybrid666

ULIK 15. Jun 2009 15:25

Re: Freigeben einer Pointerstruktur
 
Wenn Du eine Struktur erzeugst, dann solltest Du die NEXT Felder in deinem Beispiel auf nil setzen. Sonst zeigen sie irgendwo hin.

Uli

quendolineDD 15. Jun 2009 15:28

Re: Freigeben einer Pointerstruktur
 
.Next ist nicht initialisiert und zeigt daher ins Nirvana.
Edit:
Und noch etwas. Zwar überprüfst du .Next mit Assigned, jedoch überprüft Assigned auch nur auf <> nil. Nun steht jedoch ein Wert <> nil in .Next und somit gibt Assigned true zurück. Daraus resultiert dann die AV.

Der.Kaktus 15. Jun 2009 15:30

Re: Freigeben einer Pointerstruktur
 
Hallo,
da es sich in Deinem Fall um eine verkettete Liste handelt, mußt Du am Ende anfangen den Speicher wieder freizugeben.

[Edit] Hatte einen Satz nicht gelesen Sorry :oops: [/Edit]

Hybrid666 15. Jun 2009 15:31

Re: Freigeben einer Pointerstruktur
 
Der.Kaktus:

Die Rekursion sorgt dafür, dass es am Ende anfängt ;)



und ja ihr habt recht, .next zeigt ins nirvana, 2 semester uni, immer wurde und eingeprügelt "initialisiert eure variablen"....irgendwie vergisst man sowas aber am ehesten ^^ danke!

himitsu 15. Jun 2009 15:34

Re: Freigeben einer Pointerstruktur
 
Zitat:

Zitat von Der.Kaktus
Hallo,
da es sich in Deinem Fall um eine verkettete Liste handelt, mußt Du am Ende anfangen den Speicher wieder freizugeben.

ja oder am Anfang und dann über eine Temp-Variable das aktuelle Objekt merken bzw. vorm Freigeben darin .Next zwischenspeichern.

Hybrid666 15. Jun 2009 20:05

Re: Freigeben einer Pointerstruktur
 
Zitat:

Zitat von himitsu
Zitat:

Zitat von Der.Kaktus
Hallo,
da es sich in Deinem Fall um eine verkettete Liste handelt, mußt Du am Ende anfangen den Speicher wieder freizugeben.

ja oder am Anfang und dann über eine Temp-Variable das aktuelle Objekt merken bzw. vorm Freigeben darin .Next zwischenspeichern.

nein muss ich nicht.

Ich prüfe ob das aktuelle element nicht nil ist, wenn ja, dann
... prüfe ob die unterliste PCommands existiert -> FreeCommand aufrufen
... prüfe ob .Next existiert, wenn ja, erst FreeMakro (Anchor.Next) aufrufen
dann erst Aktuelles element freigeben


das heißt, die rekursion ist so aufgebaut, das vor dem zerstören des aktuellen elements, erst das nächste zerstört wird, also muss ich nix mit temp elementen speichern oder ähnliches, es ist gewährt das das freigeben hinten anfängt, nicht vorne.

MfG

quendolineDD 15. Jun 2009 20:11

Re: Freigeben einer Pointerstruktur
 
Deswegen sprach er ja eine Variante an, welche nicht rekursiv ist.

omata 15. Jun 2009 20:13

Re: Freigeben einer Pointerstruktur
 
Versuch es mal so...
Delphi-Quellcode:
procedure TForm1.Button4Click(Sender: TObject);
var
  Anchor : PMakro;
begin
  new (Anchor);
  Anchor^.TimeStamp := 10;
  Anchor^.Next := nil;
  new (Anchor^.Commands);
  Anchor^.Commands^.KeyInput := True;
  Anchor^.Commands^.Next := nil;
  FreeMakro (Anchor);
end;

Hybrid666 16. Jun 2009 11:24

Re: Freigeben einer Pointerstruktur
 
Zitat:

Zitat von quendolineDD
Deswegen sprach er ja eine Variante an, welche nicht rekursiv ist.

oh, sorry, hatte das "oder" überlesen und mir ein und hingedacht :D mein fehler ^^

Reinhard Kern 16. Jun 2009 15:44

Re: Freigeben einer Pointerstruktur
 
Zitat:

Zitat von Hybrid666
das heißt, die rekursion ist so aufgebaut, das vor dem zerstören des aktuellen elements, erst das nächste zerstört wird, also muss ich nix mit temp elementen speichern oder ähnliches, es ist gewährt das das freigeben hinten anfängt, nicht vorne.

MfG

Hallo,

Rekursion ist sehr beliebt bei Lehrern, ist elegant zu formulieren und man kann mit seinen Kenntnissen angeben, aber in der Praxis ist Rekursion fast immer Mist: wenn du 5000 Objekte hast, hast du 5000 ineinander verschachtelte Prozeduren. Das ist nicht nur völlig überflüssig, sondern auch nicht besonders gut zu debuggen.

Gruss Reinhard

Hybrid666 17. Jun 2009 08:02

Re: Freigeben einer Pointerstruktur
 
Zitat:

Zitat von Reinhard Kern
Zitat:

Zitat von Hybrid666
das heißt, die rekursion ist so aufgebaut, das vor dem zerstören des aktuellen elements, erst das nächste zerstört wird, also muss ich nix mit temp elementen speichern oder ähnliches, es ist gewährt das das freigeben hinten anfängt, nicht vorne.

MfG

Hallo,

Rekursion ist sehr beliebt bei Lehrern, ist elegant zu formulieren und man kann mit seinen Kenntnissen angeben, aber in der Praxis ist Rekursion fast immer Mist: wenn du 5000 Objekte hast, hast du 5000 ineinander verschachtelte Prozeduren. Das ist nicht nur völlig überflüssig, sondern auch nicht besonders gut zu debuggen.

Gruss Reinhard

Muss ganz ehrlich sagen, ich teil deine meinung nicht. "und man kann mit seinen Kenntnissen angeben" -> ich denk jeder Programmierer sollte was von Rekursion wissen, das hat nichts mit angeben zu tun.

Rekursion kann extrem Praktisch sein, auch bei 5000 ineinander verschachtelten elementen. Wenn man seine verschachtelung versteht, dann geht das auch mit der Rekursion.

Und um rekursion zu verstehen muss man eben rekursion verstanden haben (hab auch anfangst gedacht WTF, aber ist so, irgendwann hats klick gemacht und ich konnt super mit rekursion umgehen).

Ein kleines Beispiel:
Versuch mal iterativ Pre-, In- oder Postorder durchläufe durch einen Binärbaum. Also da find ich die Rekursion deutlich einfacher zu debuggen als iterationen mit einer queue (wüsse jetzt nicht wie das anders geht).

Oder wenn ich eine Ordnerstruktur durchlaufen will um z.B. dateien zu suchen, ich denk nichtmal das die Windowssuche das iterativ macht.

Also wie gesagt, in vielen Bereichen ist Rekursion der Iteration deutlich vorzuziehen. (mach z.B. mal obige Freigabeprozeduren iterativ, dann schauen wir mal was übersichtlicher ist).

Aber jetzt hab ich genug "mit meinen Kenntnissen angegeben".

MfG

Reinhard Kern 17. Jun 2009 14:48

Re: Freigeben einer Pointerstruktur
 
Zitat:

Zitat von Hybrid666
Also wie gesagt, in vielen Bereichen ist Rekursion der Iteration deutlich vorzuziehen. (mach z.B. mal obige Freigabeprozeduren iterativ, dann schauen wir mal was übersichtlicher ist).

Aber jetzt hab ich genug "mit meinen Kenntnissen angegeben".

MfG

Hallo,

dabei hast du eine iterative Lösung schon selbst fast erwähnt:
"... prüfe ob .Next existiert, wenn ja, erst FreeMakro (Anchor.Next) aufrufen
dann erst Aktuelles element freigeben "

Ich würde die Liste von vorne durchlaufen und immer zuerst Next zwischenspeichern, bevor das aktuelle Element freigegeben wird.

Gruss Reinhard

Hybrid666 17. Jun 2009 15:14

Re: Freigeben einer Pointerstruktur
 
Zitat:

Zitat von Reinhard Kern
dabei hast du eine iterative Lösung schon selbst fast erwähnt:
"... prüfe ob .Next existiert, wenn ja, erst FreeMakro (Anchor.Next) aufrufen
dann erst Aktuelles element freigeben "

Ich glaub du solltest dir erstmal klar drüber werden was rekursion ist...
Rekursion heißt die Funktion ruft sich selbst wieder auf, das heißt wenn ich in FreeMakro wieder FreeMakro aufrufe, dann IST das rekursion und kein iterativer ansatz!

Reinhard Kern 17. Jun 2009 15:16

Re: Freigeben einer Pointerstruktur
 
[quote="Reinhard KernIch würde die Liste von vorne durchlaufen und immer zuerst Next zwischenspeichern, bevor das aktuelle Element freigegeben wird.
[/quote]

Vorschlag:

Delphi-Quellcode:
destructor TMyObjectList.Destroy; override;
var CurrentObject,NextObject : TMyObject;

begin
CurrentObject := FirstObject; { wie auch immer }
if Assigned (CurrentObject) then { könnte ja leer sein }
  repeat
    NextObject := CurrentObject.Next;
    CurrentObject.Destroy;
    CurrentObject := NextObject;
  until not Assigned (CurrentObject;
inherited Destroy;
end;
Gruss Reinhard

Hybrid666 17. Jun 2009 15:18

Re: Freigeben einer Pointerstruktur
 
und wo gibst du (wie in meinem fall) die 2. unterliste frei? dann wird der code nämlich schon länger.

Reinhard Kern 17. Jun 2009 15:25

Re: Freigeben einer Pointerstruktur
 
Zitat:

Zitat von Hybrid666
Ich glaub du solltest dir erstmal klar drüber werden was rekursion ist...
Rekursion heißt die Funktion ruft sich selbst wieder auf, das heißt wenn ich in FreeMakro wieder FreeMakro aufrufe, dann IST das rekursion und kein iterativer ansatz!

Danke für die Belehrung, Rekursion habe ich schon mit Jensen und Wirth gelernt, das war so etwa vor 25-30 Jahren. Aber deine Beschreibung kann genausogut Grundlage eines iterativen Verfahrens sein, das siehst du bloss nicht.

Gruss Reinhard


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