AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Warum geht FreeAndNil nicht?

Ein Thema von ford42 · begonnen am 6. Aug 2018 · letzter Beitrag vom 6. Aug 2018
Antwort Antwort
ford42

Registriert seit: 2. Okt 2015
60 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#1

Warum geht FreeAndNil nicht?

  Alt 6. Aug 2018, 09:34
Delphi-Version: 10.2 Tokyo
Hey,

wenn ich FreeAndNil in der Delete-Methode verwende bekomme ich einen Zugriffsfehler.

https://pastebin.com/9Rj84HKn

Weiß jemand wieso?


Vielen Dank
LG ford

[Edit: mkinzler]
Delphi-Quellcode:
unit UnitVerkettetListe;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  PNode = ^TNode;
  TNode = record
    data: String;
    previous: PNode;
    next: PNode;
  end;
  TForm1 = class(TForm)
    Lbl_Show: TLabel;
    Bt_Back: TButton;
    Bt_Insert: TButton;
    Bt_Vorward: TButton;
    Ed_Insert: TEdit;
    Bt_Delete: TButton;
    procedure Bt_InsertClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure RefreshButtons;
    procedure Bt_BackClick(Sender: TObject);
    procedure Bt_VorwardClick(Sender: TObject);
    procedure RefreshLbl;
    procedure Bt_DeleteClick(Sender: TObject);
    procedure Refresh;
  private
    { Private-Deklarationen }
    PCurrentNode: PNode;
    PFirstNode: PNode;
    PLastNode: PNode;
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Bt_BackClick(Sender: TObject);
begin
  PCurrentNode := PCurrentNode.previous;
  Refresh;
end;

procedure TForm1.Bt_DeleteClick(Sender: TObject);
var
  PBufferNode: PNode;
begin
  if PCurrentNode.previous <> nil then
  begin
    PCurrentNode := PCurrentNode.previous;
    PBufferNode := PCurrentNode.next;
    if PCurrentNode.next.next <> nil then
    begin
      PCurrentNode.next := PCurrentNode.next.next;
    end
    else
    begin
      PCurrentNode.next := nil;
    end;
    if PBufferNode.next <> nil then
    begin
      PBufferNode.next.previous := PBufferNode.previous;
    end;
    PBufferNode := nil;
    Refresh;
    //PBufferNode.previous := nil;
    //PBufferNode.next := nil;
    //FreeAndNil(PBufferNode);
  end
  else if PCurrentNode.next <> nil then
  begin
    PCurrentNode := PCurrentNode.next;
    PBufferNode := PCurrentNode.previous;
    if PCurrentNode.previous.previous <> nil then
    begin
      PCurrentNode.previous := PCurrentNode.previous.previous;
    end
    else
    begin
      PCurrentNode.previous := nil;
    end;
  PBufferNode := nil;
  Refresh;
  end
  else
  begin
    PCurrentNode := nil;
    Bt_Back.Enabled := False;
    Bt_Vorward.Enabled := False;
    RefreshLbl;
  end;
end;

procedure TForm1.Bt_InsertClick(Sender: TObject);
begin
  New(PCurrentNode);
  PCurrentNode.data := Ed_Insert.Text;
  Ed_Insert.Text := '';
  PCurrentNode.previous := nil;
  PCurrentNode.next := nil;

  if PFirstNode = nil then
  begin
    PFirstNode := PCurrentNode;
  end
  else
  begin
    PLastNode.next := PCurrentNode;
    PCurrentNode.previous := PLastNode;
  end;
  PLastNode := PCurrentNode;
  Refresh;

end;

procedure TForm1.Bt_VorwardClick(Sender: TObject);
begin
 PCurrentNode := PCurrentNode.next;
 Refresh;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 Bt_Back.Enabled := False;
 Bt_Vorward.Enabled := False;
 PFirstNode := nil;
 PLastNode := nil;
end;

procedure TForm1.RefreshButtons;
begin
  if PCurrentNode.previous <> nil then
  begin
    Bt_Back.Enabled := True;
  end
  else
  begin
    Bt_Back.Enabled := False;
  end;

  if PCurrentNode.next <> nil then
  begin
    Bt_Vorward.Enabled := True;
  end
  else
  begin
    Bt_Vorward.Enabled := False;
  end;

end;

procedure TForm1.RefreshLbl;
begin
  if PCurrentNode <> nil then
  begin
    Lbl_Show.Caption := PCurrentNode.data;
  end
  else
  begin
    Lbl_Show.Caption := '';
  end;
end;

procedure TForm1.Refresh;
begin
  RefreshButtons;
  RefreshLbl;
end;


end.
[/edit]

Geändert von mkinzler ( 6. Aug 2018 um 09:42 Uhr) Grund: Besser hier anhängen.
  Mit Zitat antworten Zitat
Fritzew

Registriert seit: 18. Nov 2015
Ort: Kehl
678 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: Warum geht FreeAndNil nicht?

  Alt 6. Aug 2018, 09:43
Was macht freeandnil?

Es geht davon aus das der Pointer ein Object ist.....
Du hast aber einen record.....

Delphi-Quellcode:
procedure FreeAndNil(var Obj);

var
  Temp: TObject;
begin
  Temp := TObject(Obj);
  Pointer(Obj) := nil;
  Temp.Free; // Hier knallt es bei Dir
end;
Und bitte die Source hier mit rein in Delphi Tags
Fritz Westermann
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.851 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Warum geht FreeAndNil nicht?

  Alt 6. Aug 2018, 09:43
Eine genauere Beschreibung Deines Problems und die Angabe der geanen Zeile wäre vielleicht auch hilfreich.
Markus Kinzler
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#4

AW: Warum geht FreeAndNil nicht?

  Alt 6. Aug 2018, 09:48
Gegenfrage:
wie sieht Dein Sourcecode aus?

Gruß
K-H

@markus
jetzt sieht jeder diese begin/end Orgie.
Da gibt es bessere Beispiele für doppelt verkettete Listen.
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector

Geändert von p80286 ( 6. Aug 2018 um 09:51 Uhr)
  Mit Zitat antworten Zitat
ford42

Registriert seit: 2. Okt 2015
60 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#5

AW: Warum geht FreeAndNil nicht?

  Alt 6. Aug 2018, 09:50
Danke!

Also muss ich es gar nicht freigeben?
  Mit Zitat antworten Zitat
Ghostwalker

Registriert seit: 16. Jun 2003
Ort: Schönwald
1.299 Beiträge
 
Delphi 10.3 Rio
 
#6

AW: Warum geht FreeAndNil nicht?

  Alt 6. Aug 2018, 09:50
Was macht freeandnil?

Es geht davon aus das der Pointer ein Object ist.....
Du hast aber einen record.....

Delphi-Quellcode:
procedure FreeAndNil(var Obj);

var
  Temp: TObject;
begin
  Temp := TObject(Obj);
  Pointer(Obj) := nil;
  Temp.Free; // Hier knallt es bei Dir
end;
Und bitte die Source hier mit rein in Delphi Tags
Jap. Außerdem wird vorher dem Zeiger Nil zugewiesen.


Freigeben musst du sehr wohl, entweder via Dispose oder FreeMem.
Passend zum Thema hier ein Tutorial
Uwe
e=mc² or energy = milk * coffee²
  Mit Zitat antworten Zitat
ford42

Registriert seit: 2. Okt 2015
60 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#7

AW: Warum geht FreeAndNil nicht?

  Alt 6. Aug 2018, 09:53
Mein Sourcecode ist doch oben?

EDIT: Die Methode sah eig vorher so aus:

Delphi-Quellcode:
procedure TForm1.Bt_DeleteClick(Sender: TObject);
var
  PBufferNode: PNode;
begin
  if PCurrentNode.previous <> nil then
  begin
    PCurrentNode := PCurrentNode.previous;
    PBufferNode := PCurrentNode.next;
    if PCurrentNode.next.next <> nil then
    begin
      PCurrentNode.next := PCurrentNode.next.next;
    end
    else
    begin
      PCurrentNode.next := nil;
    end;
    if PBufferNode.next <> nil then
    begin
      PBufferNode.next.previous := PBufferNode.previous;
    end;
    //PBufferNode := nil;
    Refresh;
    //PBufferNode.previous := nil;
    //PBufferNode.next := nil;
    FreeAndNil(PBufferNode);
  end
  else if PCurrentNode.next <> nil then
  begin
    PCurrentNode := PCurrentNode.next;
    PBufferNode := PCurrentNode.previous;
    if PCurrentNode.previous.previous <> nil then
    begin
      PCurrentNode.previous := PCurrentNode.previous.previous;
    end
    else
    begin
      PCurrentNode.previous := nil;
    end;
  FreeAndNil(PBufferNode);
  Refresh;
  end
  else
  begin
    FreeAndNil(PCurrentNode);
    //PCurrentNode := nil;
    Bt_Back.Enabled := False;
    Bt_Vorward.Enabled := False;
    RefreshLbl;
  end;
end;
  Mit Zitat antworten Zitat
Klaus01

Registriert seit: 30. Nov 2005
Ort: München
5.755 Beiträge
 
Delphi 10.4 Sydney
 
#8

AW: Warum geht FreeAndNil nicht?

  Alt 6. Aug 2018, 10:06
Delphi-Quellcode:
   PBufferNode := nil;
    Refresh;
    //PBufferNode.previous := nil;
    //PBufferNode.next := nil;
    //FreeAndNil(PBufferNode);
bleibt dasPBufferNode := nil stehen wenn Du freeAndNil einfügst?

Grüße
Klaus
Klaus
  Mit Zitat antworten Zitat
Ghostwalker

Registriert seit: 16. Jun 2003
Ort: Schönwald
1.299 Beiträge
 
Delphi 10.3 Rio
 
#9

AW: Warum geht FreeAndNil nicht?

  Alt 6. Aug 2018, 10:20
Wie Fritz schon sagte, arbeitet FreeAndNil mit Objekt-Instanzen, nicht mit typisierten Zeigern.

Da es sich um einen typisierten Zeiger handelt kannst du das ganze mit Dispose freigeben.
Uwe
e=mc² or energy = milk * coffee²
  Mit Zitat antworten Zitat
Fritzew

Registriert seit: 18. Nov 2015
Ort: Kehl
678 Beiträge
 
Delphi 11 Alexandria
 
#10

AW: Warum geht FreeAndNil nicht?

  Alt 6. Aug 2018, 10:23
Ok um das zu vervollständigen:
Delphi-Quellcode:
// Anstatt
// FreeAndNil(PBufferNode);
// so:
 dispose(PBufferNode); // Freigeben des Nodes
 PBufferNode := nil;
 Refresh;
Fritz Westermann
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:50 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