AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi TList mit "verschiedenen Pointern" freigeben
Thema durchsuchen
Ansicht
Themen-Optionen

TList mit "verschiedenen Pointern" freigeben

Ein Thema von Mattze · begonnen am 24. Apr 2007 · letzter Beitrag vom 29. Mai 2007
Antwort Antwort
Seite 2 von 2     12   
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#11

Re: TList mit "verschiedenen Pointern" freigeben

  Alt 25. Apr 2007, 17:39
wie bereits erwähnt könnten beide Recordtypen am Anfang des Records ein Feld haben welches den Typ angibt. Mit einem Cast auf einen der beiden Recordtypen kannst du dann prüfen welcher Typ tatsächlich in der Liste hängt.

Zum Vorschlag einfach
dispose(liste.Items[i]) zu verwenden:
Generell sollte das funktionieren. Allerdings habe ich gelesen (weiß nicht obs stimmt) das bei Records in denn Strings etc. enthalten sind von denen der Speicher nicht frei gegeben wird.

[Edit]
ich habs inzwischen mal "getestet".
Ohne Cast auf den Typ (dispose(liste.Items[i])) wird intern FreeMem aufgerufen
Mit Cast auf den Typ (dispose(PRecordTyp(liste.Items[i]))) wird intern Dispose aufgerufen

und dispose ruft intern Finalize auf was wiederum FinalizeArray aufruft was wohl dynamische Arrays und Strings frei gibt.
[/Edit]
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
Benutzerbild von 3_of_8
3_of_8

Registriert seit: 22. Mär 2005
Ort: Dingolfing
4.129 Beiträge
 
Turbo Delphi für Win32
 
#12

Re: TList mit "verschiedenen Pointern" freigeben

  Alt 25. Apr 2007, 18:08
Wie kann denn FreeMem aufgerufen werden, wenn Dispose gar nicht "weiß", wie viel Speicher freigegeben werden darf?
Manuel Eberl
„The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.“
- Terry Pratchett
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#13

Re: TList mit "verschiedenen Pointern" freigeben

  Alt 25. Apr 2007, 18:59
@Sir: Habs auch getestet und kann all deine Vermutungen bestätigen.

@3_of_8
Wenn der Compiler bei dispose einen untypisierten pointer (also list.items[i] : pointer) erkennt ruft er automatisch nur freemem auf. Vor jedem alloziierten Speicherplatz steht desen Größe (und noch ein bisschen mehr) Wenn du also mit Getmem 10 Bytes alloziierst, dann steht bei addr(list.items[i]-4) eine 10, wenn du einen string hast (z.B. s:='Hallo'), dann steht dort (bei addr(@s-4)eine 5), somit kann freemem, ohne Größenangabe speicher freigeben, denn die Größenangabe steht ja vor dem Datentyp (egal welcher, für arrays gilt dasgleiche)
Dort steht allerdings weder ne 10 noch ne 5. sondern an der Stelle sind mehrere Werte versteckt, aber mann kann es eineindeutig zurücktransformieren (zu 10 und 5)

Der angesprochene Unterschied, den Sir meinte, ist wenn ich dispose(PRecord1(list.items[i])) mache, dann ruft der Compiler auch tatsächlich dispose auf. Und Dispose ruft intern das angesprochene Finalize (etc. auf) und hinterher freemem. also ist der Unterschied nur, in dem finalize. Und ich habe gerade überprüft: Finalize gibt tatsächlch den Speicher von Arrays, strings, etc frei.
Nun, woher weis finalize, wo die strings im Record liegen? Versteckt übergibt der compiler bei dispose noch einen zweiten Parameter. Dies ist eine Adresse im Datensegment und beinhaltet die Struktur des Records. Und jetzt schließt sich der Kreis. Damit weis finalize, was und wo es noch strings, arrays, sonstige dynamische Variablen freigeben muss. Und zum zweiten ist es jetzt auch klar, warum wir den Typecast auf PRecord1 brauchen: Der Compiler muss ja auch wissen, welchen zweiten Parameter er an dispose übergeben muss.

Zusammenfassung:
aus dispose(list.items[i]) wird freemem(list.items[i])
aus dispose(PRecord1(list.items[i])) wird dispose(list.items[i],addr(Precord1Structure))


So, und jetzt noch eine neue Lösung für oben genanntes Problem:
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type Pp1=^Rp1;
     Rp1=record
       //typ ist für die wiedererkennung des Records
       typ:byte;
       //ab hier können jetzt statische und/oder dynamische Variablen folgen
       s:string;
     
     end;
type Pp2=^Rp2;
     Rp2=record
       //wir das obige Record
       typ:byte;
       s:array of integer;
       x:byte;
     end;
type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure fill;
    procedure clear;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
    list:Tlist;
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}


procedure Tform1.fill;
var p1:Pp1;
    p2:Pp2;
begin
  list:=Tlist.create;
  new(p1);
  p1^.typ:=1; //Typ zum wiedererkennen festlegen
  p1^.s:='Hallo';

  new(p2);
  p2^.typ:=2;
  setlength(p2^.s,2);
  p2^.s[0]:=10;
  p2^.s[1]:=20;

  list.add(p2);
  list.add(p1);

  new(p1);
  p1^.typ:=1;
  p1^.s:='';
  list.add(p1);

end;
procedure Tform1.clear;
var i:integer;
    typ:pbyte;
begin
  for i:=0 to list.Count-1 do begin
    typ:=list[i];
    case typ^of
      1: dispose(Pp1(list[i]));
      2: dispose(Pp2(list[i]));
      else raise Exception.CreateFmt('$d ist kein gültiger Recordtyp!',[typ^]);
    end;
  end;
  list.free;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  fill;
  clear;
end;

end.
Was bei allen tollen Funktionen auch der Compiler nicht schaffen wird, sind speicherbereiche freigeben, auf die ein untypisierter Pointer innerhalb des records zeigt
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
Mattze

Registriert seit: 6. Jan 2005
664 Beiträge
 
#14

Re: TList mit "verschiedenen Pointern" freigeben

  Alt 29. Mai 2007, 18:32
Hallo,

'tschuldigung. Ging jetzt eine Weile nicht bei mir!
Aber jetzt!
Vielen Dank für Eure Hilfe.
Inzwischen klappt es und natürlich klappt es so, wie es ja auch klappen muss - mit dispose.
Es war ein echt dummer gedanklicher Fehler von mir. Ich habe "die Reichweite von Assign" unlogisch hoch angesetzt.

Gruß
Mattze
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 2     12   


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:41 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