AGB  ·  Datenschutz  ·  Impressum  







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

Zeiger freigeben

Ein Thema von TomDooley · begonnen am 16. Jun 2005 · letzter Beitrag vom 21. Jun 2005
Antwort Antwort
Seite 1 von 2  1 2      
TomDooley

Registriert seit: 26. Jan 2004
124 Beiträge
 
#1

Zeiger freigeben

  Alt 16. Jun 2005, 19:42
Hallo

Beim Freigeben von Zeiger habe ich nicht ganz den Durchblick. Gegeben ist folgender Code (von zwei Klassen):

Delphi-Quellcode:
function TTestClassA.getListe: TList;
var
  List : TList;
  PTestRecord : ^TTestRecord;
begin
  new(PTestRecord);
  List := TList.Create;
  PTestRecord^.FeldA := 'Hallo';
  PTestRecord^.FeldB := 'Test';
  PTestRecord^.FeldC := 1;
  List.Add(PTestRecord);
  Result := List;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  List : TList;
  TestClassA : TTestClassA;
  PTestRecord : ^TTestRecord;
begin
  TestClassA := TTestClassA.Create;
  List := TestClassA.getListe;
  PTestRecord := List.Items[0];
  Label1.Caption := PTestRecord^.FeldA;
  Dispose(PTestRecord);
end;
Soll ich nun den Zeiger wie ich's gemacht habe in der zweiten Funktion disposen oder macht man in solchen Fällen in der TestClassA eine Prozedur, die dann einfach dispose(PTestRecord) aufruft (und in der Button1Click-Prozedur aufgerufen wird)?
Die selbe Frage stellt sich natürlich auch wenn man statt mit TList mit TObjectList arbeiten würde (und dann Objekte auflistet). Dann würde aber nur der Weg über eine Funktion der Klasse TTestClassA funtktionieren, oder?

Ich wäre froh wenn mir jemand den "Standardweg" aufzeigen könnte.

Danke und Gruss

Tom
  Mit Zitat antworten Zitat
16. Jun 2005, 19:44
Dieses Thema wurde von "alcaeus" von "Programmieren allgemein" nach "Object-Pascal / Delphi-Language" verschoben.
Ist eine Frage zu Object Pascal
Muetze1
(Gast)

n/a Beiträge
 
#3

Re: Zeiger freigeben

  Alt 16. Jun 2005, 22:14
Moin!

Zitat von TomDooley:
Soll ich nun den Zeiger wie ich's gemacht habe in der zweiten Funktion disposen oder macht man in solchen Fällen in der TestClassA eine Prozedur, die dann einfach dispose(PTestRecord) aufruft (und in der Button1Click-Prozedur aufgerufen wird)?
Nach dem Dispose() zeigt aber der erste Eintrag der Liste ins Nirvana, da du den Speicherbereich freigegeben hast, wo der Record liegt und wo der Eintrag der Liste hinzeigt. Die Liste gibt dir ja nur einen Pointer zurück auf die Stelle im Speicher wo der Record liegt. Nun musst du aber den reinen Pointer den du beim Button Click bekommst aber nicht freigeben, da es wie eine Integer Variable ist - und die musste auch nicht freigeben.

Grundsätzlich musst du den Speicher für den Record freigeben, wenn du den Eintrag löscht in der Liste - weil die Liste verwaltet nur Zeiger, die zweiss nix von dem Typ und kann daher auch nicht den Speicher freigeben.

Zitat von TomDooley:
Die selbe Frage stellt sich natürlich auch wenn man statt mit TList mit TObjectList arbeiten würde (und dann Objekte auflistet). Dann würde aber nur der Weg über eine Funktion der Klasse TTestClassA funtktionieren, oder?
Da ist es ja so, das du auch nur eine Referenz auf das Objekt bekommst. Würdest du das Objekt freigeben, dann zeigt der Eintrag der Objektliste an der Stelle ins Nirvana, weil das Objekt weg ist. Daher würde ein späterer Zugriff auf das Objekt krachen.

Ausserdem hat die TObjectlist die einfache Möglichkeit das man ihr sagen kann (ist sogar Standardeinstellung ->OwnsObjects), dass sie beim Entfernen eines Objektes aus der Liste, dieses auch freigibt (->Delete()). Wenn dies nicht gewünscht ist, dann kann man auch Remove() nutzen, welches das Objekt zurück gibt, den Eintrag aus der Liste entfernt aber das Objekt nicht freigibt.

MfG
Muetze1
  Mit Zitat antworten Zitat
TomDooley

Registriert seit: 26. Jan 2004
124 Beiträge
 
#4

Re: Zeiger freigeben

  Alt 17. Jun 2005, 10:15
Tag auch

Danke erstmal für die Infos. Vielleicht erst zu den Zeigern:

Das Dispose in Button1Click ist demzufolge unnötig. Wie und vor allem wann müsste aber nun in meinem Beispiel Dispose aufgerufen werden? Sehe ich das zudem richtig dass ich mit TList ein Speicherleck geschaffen habe (List wird in getListe nicht zerstört, darf aber auch nicht sein da ansonsten in Button1Click nicht mehr verfügbar --> wann und wie soll ich List freigeben?).

Ich wäre froh wenn jemand mein Bespiel so ändern könnte, das alles richtig funktioniert und schlussendlich richtig freigegeben wird.

Danke und Gruss

Tom
  Mit Zitat antworten Zitat
TomDooley

Registriert seit: 26. Jan 2004
124 Beiträge
 
#5

Re: Zeiger freigeben

  Alt 20. Jun 2005, 12:19
Ich hab's mal selbst probiert:

Delphi-Quellcode:
function TTestClassA.getListe: TList;
var
  List : TList;
begin
  new(PTestRecord);
  List := TList.Create;
  PTestRecord^.FeldA := 'Hallo';
  PTestRecord^.FeldB := 'Test';
  PTestRecord^.FeldC := 1;
  List.Add(PTestRecord);
  Result := List;
  List.Free;
end;

procedure TTestClassA.Destroy;
begin
  Dispose(PTestRecord);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  List : TList;
  TestClassA : TTestClassA;
  PTestRecordKopie : ^TTestRecord;
begin
  TestClassA := TTestClassA.Create;
  List := TestClassA.getListe;
  PTestRecordKopie := List.Items[0];
  Label1.Caption := PTestRecordKopie^.FeldA;
  List.Free;
  TestClassA.Destroy;
end;
PTestRecord in TTestClassA müsste als Membervariable von TTestClassA definiert werden damit sie in Destroy zerstört werden kann.
Stimmt das so?

Danke und Gruss

Tom
  Mit Zitat antworten Zitat
Benutzerbild von Khabarakh
Khabarakh

Registriert seit: 18. Aug 2004
Ort: Brackenheim VS08 Pro
2.876 Beiträge
 
#6

Re: Zeiger freigeben

  Alt 20. Jun 2005, 12:56
  • Sollte PTestRecord nicht eher im Konstruktor "gefüllt" werden?
  • Destroy ist keine normale Prozedur, sondern ein Destruktor. Man sollte immer den Destruktor der Basisklasse überschreiben und am Ende inherited aufrufen:
    Delphi-Quellcode:
    destructor TTestClassA.Destroy;
    begin
      Dispose(PTestRecord);
      inherited;
    end;
  • TestClassA.Destroy; Du solltest immer Free statt Detroy zum Freigeben einer Instanz aufrufen. Wenn du den Destruktor wie oben beschrieben korrigierst, wird bei Free auch dein eigener aufgerufen.
  • Delphi-Quellcode:
    Result := List;
      List.Free;
    ?
  • Nimm doch statt der Prozedur GetList eine read-only Property.
Sebastian
Moderator in der EE
  Mit Zitat antworten Zitat
TomDooley

Registriert seit: 26. Jan 2004
124 Beiträge
 
#7

Re: Zeiger freigeben

  Alt 20. Jun 2005, 13:20
Zitat:
Sollte PTestRecord nicht eher im Konstruktor "gefüllt" werden?
Ich gehe davon aus, dass der Speicher bei Bedarf reserviert wird und nach der "Verarbeitung" gleich wieder freigegeben wird (siehe nächste Anmerkung).

Zitat:
Destroy ist keine normale Prozedur, sondern ein Destruktor.
Ich weiss, ich wollte damit nur demonstrieren, dass der Speicher freigegeben wird (so gesehen eine etwas schlechte Namenswahl von mir). Diese Prozedur wird also nicht beim Freigeben des Objekts sondern unmittelbar nach dem "Benutzen" von PTestRecord aufgerufen.

Zitat:
Nimm doch statt der Prozedur GetList eine read-only Property
Danke für den Tip. Es geht hier in erster Linie aber darum, wie mit Zeigern umgegangen werden soll.
  Mit Zitat antworten Zitat
TomDooley

Registriert seit: 26. Jan 2004
124 Beiträge
 
#8

Re: Zeiger freigeben

  Alt 21. Jun 2005, 13:25
Hallo alle,

das mit dem Freigeben vom Listenobjekt habe ich inzwischen so gelöst, indem ich die Liste der function getListe als var-Parameter übergebe. Es bleibt aber immer noch die Frage, wo und wann ich den mit new(PTestRecord) reservierten Speicher freigeben kann/soll... (ich denke ich kann new(PTestRecord) nicht im Konstruktor aufrufen da ich nicht weiss wie oft die Funktion getListe nacheinander aufgerufen wird)

Danke und Gruss
Tom
  Mit Zitat antworten Zitat
runger
(Gast)

n/a Beiträge
 
#9

Re: Zeiger freigeben

  Alt 21. Jun 2005, 13:34
Hallo,

ein kurzer Kommentar:

einen Zeiger kann man nicht freigeben, höchstens reservierten Speicher!
Ein Zeiger ist nichts als eine Adresse.

Rainer
  Mit Zitat antworten Zitat
Robert_G
(Gast)

n/a Beiträge
 
#10

Re: Zeiger freigeben

  Alt 21. Jun 2005, 14:07
Warum willst du unbedingt it records und Zeigern arbeiten?

Alki hat in der CodeLib ein Hier im Forum suchenObjectList template platziert.
Damit ist folgendes möglich:

Eine Klasse, die dein Item darstellt (die Liste wird durch ein paar Extra runden des Compilers angelegt ):
Delphi-Quellcode:
uses Contnrs;

type
   TTest = class
   private
      fSomeValue: Integer;
   public
      property SomeValue: Integer read fSomeValue;
      procedure DoSomething;
      constructor Create(aSomeValue :Integer); virtual;
   end;

   _LIST_ITEM_ = TTest;
{$DEFINE TYPED_LIST_TEMPLATE}
{$INCLUDE ObjList_Tmpl.pas}
   TTestList = _LIST_;

implementation

{$INCLUDE ObjList_Tmpl.pas}

{ TestClass }

constructor TTest.Create(aSomeValue: Integer);
begin
   fSomeValue := aSomeValue;

end;

procedure TTest.DoSomething;
begin
   Writeln(SomeValue);
end;
Die Verwendung ist absolut easy.
Delphi-Quellcode:
procedure TTestUsage.DoSomething;
var
   List : TTestList;
   Item : TTest;
   Counter : Integer;
begin

   List := TTestList.Create();
   try

      for Counter := 1 to 100 do
      begin
         Item := TTest.Create(Counter);
         List.Add(Item);
      end;

      for Counter := 0 to List.Count do
      begin
         List[Counter].DoSomething(); // ohne type cast :-)
      end;

   finally
      List.Free();
   end;
end;
Ohne ^, @, Typecasts, anderes Gefriemel... (Die Typecasts sind ja schon im Template versteckt )
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 17:53 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