Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi vergisst die Werte der Eigenschaften meiner Klasse (https://www.delphipraxis.net/162512-delphi-vergisst-die-werte-der-eigenschaften-meiner-klasse.html)

Andre93 25. Aug 2011 18:14

Delphi vergisst die Werte der Eigenschaften meiner Klasse
 
hey...
also ich habe folgendes problem und ich würde mich wirklich sehr freuen wenn mir irgendjemand hier weiter helfen kann:
ich habe eine Klasse TData erstellt.
Diese hat die Eigenschaften :
_Data : Pointer;
_MaxSize, _RealSize, _DataType : Integer;
und die Prozeduren :
procedure Init(MaxSize, DataType : Integer);
procedure Input(Data : Pointer; RealSize : Integer);
procedure Output(var Data : Pointer);

Die Prozedur Init soll nach dem create von TData den Eigenschaften _MaxSize, und _DataType einen Wert zuweisen.
Mit der Prozedur Input kann ich dann ein "Datenpaket" ,das durch den Pointer _Data representiert wird dazu packen und in der Eigenschaft _RealSize die wirkliche Größe des "Datenpakets" festhalten.
Mit der Prozedur Output will ich das "Datenpaket" dann wieder herausholen. Für das herausholen wollte ich dann durch _RealSize heraufinden wie groß das "Datenpaket" ist.

Soweit zur Theorie!
In der Praxis allerdings vergisst Delphi die Werte der Eigenschaften.
Das heißt wenn ich zum Beispiel bei Input _RealSize den Wert 11 zugewiesen habe, dann hatte _RealSize beim Aufruf von Output auf einmal den Wert 13514484 und _MaxSize den Wert 4372840 (zuvor hatte ich den Wert 500 abgespeichert).
Ganz so als würde Delphi den Speicherplatz für die Eigenschaften wieder freigeben weil es der Meinung ist das die Eigenschaften jetzt für nichts mehr gebraucht werden könnten.
Komisch ist auch, dass nicht immer alle Werte verloren gehen. Teilweise ist auch nur der Wert für _MaxSize verschwunden und _RealSize geblieben oder anders herum.

Ich wäre wirklich sehr dankbar wenn mir jemand erklären könnte was ich falsch gemacht habe oder mir eventuell einen Tip geben könnte wie ich dieses Problem umgehe. Folgend füge ich auch noch einmal den Quelltext an.

Schon einmal vielen Dank im voraus
Andre

Unit die die Klasse enthält :

Delphi-Quellcode:
unit U_Data;

interface

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

const
 dtNone   = -1;
 dtBool   = 0;
 dtByte   = 1;
 dtChar   = 2;
 dtString = 3;
 dtInteger = 4;
 dtReal   = 5;

type

 TArByte = array of Byte;

 TData = class
  private
   _Data : Pointer;
   _MaxSize, _RealSize, _DataType : Integer;
  public
   procedure Init(MaxSize, DataType : Integer);
   procedure Input(Data : Pointer; RealSize : Integer);
   procedure Output(var Data : Pointer);
 end;

implementation

procedure TData.Init(MaxSize, DataType : Integer);
begin
 _MaxSize := MaxSize;
 _DataType := DataType;
end;

procedure TData.Input(Data : Pointer; RealSize : Integer);
begin
 if RealSize <= _MaxSize then
  begin
   _RealSize := RealSize;
   GetMem(_Data, RealSize);
   Move(Data, _Data, RealSize);
  end
 else
  ShowMessage('Speicherplatz überschritten!');
end;

procedure TData.Output(var Data : Pointer);
begin
 GetMem(Data,_RealSize);
 Move(_Data,Data,_RealSize);
end;
Unit des Hauptprogrammes (Hier wollte ich die Prozeduren mal ausprobieren) :

Delphi-Quellcode:
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Edit1: TEdit;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  D : TData;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
 D := TData.Create;
 D.Init(500,1);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
 arB : array[0..10]of Byte;
 I : Integer;
begin
 for I := 0 to 10 do
  arB[I] := I;
 D.Input(@arB,SizeOf(arB));
end;

procedure TForm1.Button3Click(Sender: TObject);
var
 arB : pointer;
 a : Tarbyte;
 I : Integer;
begin
 D.OutPut(arB);
 a := TArByte(arb);
 for I := 0 to 10 do
  Caption := Caption + IntToStr(a[I]);
end;

end.

Uwe Raabe 25. Aug 2011 18:24

AW: Delphi vergisst die Werte der Eigenschaften meiner Klasse
 
Ändere mal diese Zeile

Delphi-Quellcode:
Move(Data, _Data, RealSize);
in diese

Delphi-Quellcode:
Move(Data^, _Data^, RealSize);

himitsu 25. Aug 2011 18:44

AW: Delphi vergisst die Werte der Eigenschaften meiner Klasse
 
Und nicht die ganzen Speicherlecks vergessen.


Der von Output reservierte Speicher wird nicht freigegeben.
Auch würde ich dort eher OUT statt VAR deklarieren, da du ja die eingehenden Werte des Parameters ignorierst.

Und wurde schonmal über Input was zugewiesen, wird bei nächster Zuweisung das vorherrige ignoriert und nicht freigegeben.
Auch wird das am Ende nicht wieder freigegeben.

Andre93 25. Aug 2011 18:45

AW: Delphi vergisst die Werte der Eigenschaften meiner Klasse
 
hey super!
das funktioniert!!
vielen vielen Dank für die schnelle hilfe.
ich hätte nie damit gerechnet dass ich so schnell eine antwort bekomme.
echt klasse.
kannst du mir vielleicht erklären warum das so geht und warum anders nicht. mit diesen ganzen pointer geschichten habe ich nämlich noch ab und zu so meine probleme. vor allem verstehe ich nicht ganz warum probleme bei den anderen eigenschaften auftreten, weil der move befehl macht ja überhaupt nichts mit diesen eigenschaften. für den sind ja eigentlich nur data, _data und die größe meines datenpaket wichtig.
würde mich echt mal interessieren, aber bis hier erst einmal danke das hat mir schon sehr geholfen

himitsu 25. Aug 2011 18:49

AW: Delphi vergisst die Werte der Eigenschaften meiner Klasse
 
Du willst doch den Inhalt kopieren und da Move als VAR/CONST Parameter deklariert ist, mußt du deine Zeiger erst dereferenzieren, damit der Inhalt übergibt wird.

Ohne Dereferenzierung kopierst du die Zeiger und nicht das worauf die Zeiger zeigen.

Bei RealSize > SizeOf(Pointer) handelst du dir dann auch noch einen Bufferoverrun ein.

Andre93 25. Aug 2011 21:38

AW: Delphi vergisst die Werte der Eigenschaften meiner Klasse
 
@himitsu
ich hab da noch mal ein paar fragen
du hast geschrieben:
Zitat:

Und wurde schonmal über Input was zugewiesen, wird bei nächster Zuweisung das vorherrige ignoriert und nicht freigegeben.
also muss ich bevor ich ein weiteres mal input mache, um die gespeicherten werte zu verändern, vorher den speicherbereich der meine alten werte beinhaltet wieder freigeben? das mach ich einfach mit
Delphi-Quellcode:
FreeMem(_Data);
oder?

Und du meintest :
Zitat:

Der von Output reservierte Speicher wird nicht freigegeben.
In Output reserviere ich doch den Speicherbereich auf den der pointer zeigt den ich beim aufruf von output übergebe. wenn ich diesen speicher gleich wieder freigebe, dann gebe ich doch das wieder frei was so zu sagen mein "rückgabewert" ist. und mit diesem "rückgabewert" will ich ja nach dem aufruf von output weiterarbeiten, da wäre es ja schlecht wenn der schon wieder freigegeben ist, oder? Tut mir leid, ich schätze ich habs falsch verstanden, weil mir hier evtl. ein paar grundlagen in sachen gesetzmäßigkeiten von übergaben usw. fehlen.

DeddyH 26. Aug 2011 07:09

AW: Delphi vergisst die Werte der Eigenschaften meiner Klasse
 
Als Faustregel gilt: 1 GetMem -> 1 FreeMem, 1 New -> 1 Dispose
Wo man das macht hängt davon ab, wie lange man die Daten braucht, aber irgendwo muss es sein (zur Not im Destruktor).

sx2008 27. Aug 2011 01:05

AW: Delphi vergisst die Werte der Eigenschaften meiner Klasse
 
Mir scheint du bist mit einem TMemoryStream oder TStringStream besser bedient als mit deiner eigenen Klasse.
Du könntest auch ein TMemoryStream-Objekt innerhalb deiner eigenen TData-Klasse benützen.

Andre93 29. Aug 2011 19:44

AW: Delphi vergisst die Werte der Eigenschaften meiner Klasse
 
hey,
bis hierher schon mal vielen dank an alle...
im moment hab ich noch ein anderes problem. das ist wahrscheinlich ein ganz einfacher fehler aber ich sitze jetzt schon ne ganze weile dran und bekomme es nicht hin.

ich wollte nun nicht immer das gleiche abspeichern, sondern nun irgendeinen Text aus einem editfeld.
bloß in dem moment wo ich das array dynamisch erzeuge funktioniert es nicht mehr.

also das hier funktioniert noch :
Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
var
 arB : array[0..10] of Byte;
 I, Len : Integer;
begin
 len := length(Edit1.Text);
 for I := 0 to len - 1 do
  arB[I] := ord(Edit1.Text[I+1]);
 D.Input(@arB,len);
end;
da ist ja schon vorher die größe arrays festgesetzt.

Das hier geht allerdings nicht mehr:
Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
var
 arB : array of Byte;
 I,Len : Integer;
begin
 len := length(Edit1.Text);
 GetMem(arB,len);
 for I := 0 to len - 1 do
  arB[I] := ord(Edit1.Text[I+1]);
 D.Input(@arB,len);
 FreeMem(arB,len);
end;
da liefert "output" nicht mehr die richtigen werte, sondern irgendwelche anderen.

himitsu 30. Aug 2011 02:23

AW: Delphi vergisst die Werte der Eigenschaften meiner Klasse
 
GetMem? :gruebel:
Delphi-Referenz durchsuchenSetLength

Welche Delphiversion nutzt du nochmal? (PS: sowas kann man auch gleich mit im Foren-Profil mit nennen)
Seit Delphi 2009 ist ein SizeOf(Char) = 2 und nicht SizeOf(Byte).

Andre93 31. Aug 2011 22:48

AW: Delphi vergisst die Werte der Eigenschaften meiner Klasse
 
hey,
sry hatte vergesse das mit der delphi version anzugeben.
also ich hab delphi 6, weil wir in der schule auch nichts neueres haben:roll:, naja auf jeden fall dürfte bei delphi 6 ja nicht der fehler auftreten von dem du redest..
ich hab das jetzt mal mit setlength gemacht und es funktioniert eigentlich auch alles. das einzig komische ist nur, dass nachdem ich mit meinem output fertig bin enthält mein "rückgabe-array" zwar die richtigen werte, wenn ich dann allerdings mit einer zählschleife das array durchakkern will um die inhalte wieder auszugeben ist der inhalt des array mit einmal nicht mehr arB : [69,100,105,116,49,...,...] sondern nur noch zuerst arB : (69), dann arB : (36), dann arB : (). wenn man sich das ganze in der watchlist anguckt sieht es auf jeden fall nachdem moment wo die schleife beginnt nich mehr wie ein array aus.

hier mein quelltext :

das hier funktioniert noch :
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
 D := TData.Create;
 D.Init(500,1);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
 arB : array of Byte;
 I,Len : Integer;
begin
 len := length(Edit1.Text);
 SetLength(arB,len);
 for I := 0 to len - 1 do
  arB[I] := ord(Edit1.Text[I+1]);
 D.Input(@arB,len);
end;
und bei dem hier hat er bis vor der schleife noch die richtigen werte im array und während der schleife läuft dann irgendwas schief :

Delphi-Quellcode:
procedure TForm1.Button3Click(Sender: TObject);
var
 P : pointer;
 arB : TArByte;
 I : Integer;
begin
 D.OutPut(P);
 SetLength(arB,D._RealSize);
 arB := TArByte(P^); //bis hier ist alles wie es sein soll
 for I := 0 to D._RealSize - 1 do
  Caption := Caption + chr(arB[I]);
end;
schönen abend noch..

himitsu 31. Aug 2011 23:54

AW: Delphi vergisst die Werte der Eigenschaften meiner Klasse
 
Wie zu erwarten war ... überall Speicherlecks.
Aber erstmal egal :roll:


Zitat:

Zitat von Andre93 (Beitrag 1120787)
Delphi-Quellcode:
D.Input(@arB,len);

Delphi-Quellcode:
@arB
= ein Zeiger auf die Variable
Delphi-Quellcode:
@arB[0]
= ein Zeiger auf die Daten
Denn ein dynamisches Array ist intern ein Zeiger und die Daten stecken nicht direkt in der Variable.
Bei einem statischen Array entspicht @arB zwar einem @arB[Low(arB)], aber besser immer mit Index ... nicht daß man es mal vergißt und es dann bei einem Dynamischen knallt.


Zitat:

Zitat von Andre93 (Beitrag 1120787)
bis hier ist alles wie es sein soll

falsch gedacht

Zitat:

Zitat von Andre93 (Beitrag 1120787)
Delphi-Quellcode:
 D.OutPut(P);
 SetLength(arB,D._RealSize);
 arB := TArByte(P^); //bis hier ist alles wie es sein soll

P gibt einen Speicherbereich (Pointer) zurück
arB ist aber kein billiger Zeiger (Delphi-Referenz durchsuchenPointer), sondern ein
Delphi-Quellcode:
array of byte
:warn:

Dann reservierst du Speicher für das dyn. array (SetLength),
welchen du dann wieder verwirfst (
Delphi-Quellcode:
:=
) und versuchst den Pointer als
Delphi-Quellcode:
array of byte
zu interpretieren,
was natürlich niemals funktionieren kann, da es vollkommen unterschiedliche Typen sind und sie ihren speicher unterschiedlich verwalten.

Du mußt also den speicher von P in das Array kopieren.
Praktisch so ähnlich, wie du schonmal den Text in das Array reinkopiert hast. (Edit1.Text ist der Inhalt von P)
Delphi-Quellcode:
 for I := 0 to len - 1 do
  arB[I] := ord(Edit1.Text[I+1]);
(statt solcher Schleifen kann man natürlich auch Delphi-Referenz durchsuchenMove verwenden)

P köntest du dir dafür nach PStaticBytes casten.
Delphi-Quellcode:
type
  TStaticBytes = array[0..0] of Byte;
  PStaticBytes = ^TStaticBytes;
PS: 0..0 ist ein sonderfall, denn dort macht Delphi niemals eine Bereichsprüfung für den Index.
Man könnte auch
Delphi-Quellcode:
[0..666]
nehmen (666 = irgendein Wert, welcher groß genug ist ... also mindestens so groß, wie der maximal zu erwartende Indexwert ... da ist [0..0] natürlich einfacher :angle2: )



Und am Ende vergißt du auch noch P wieder freizugeben, welches in OutPut reserviert wurde.
Darum macht man sowas eigentlich auch besser nicht ... Speicher sollte möglichst immer in der Ebene freigeben werden, wo er reserviert wurde.

Mach Output genauso wie input (Pointer+Len) und laß' die Daten vom Output direkt in @arB[0] reinschreiben.
(Len ist dann die Länge von arB, also die maximale Größe der daten, welche in arb reinpassen würde, was man in Output prüfen sollte, bevor man was reinschreibt)








Delphi-Quellcode:
TBytes = array of Byte; // in neueren Delphis kann man das dann weglassen, da es diesen Typ dort schon gibt

TDataType = (dtNone, dtBool, dtByte, dtChar, dtString, dtInteger, dtReal); // ein Enumerator

TData = class
 private
  _Data : Pointer;
  _MaxSize, _RealSize: Integer;
  _DataType : TDataType;
 public
  procedure Init(MaxSize : Integer; DataType : TDataType); // wäre als Constructor bestimmt besser geeignet
  destructor Destroy; override;

  procedure Input(Data : Pointer; DataSize : Integer);

  property MaxSize: Integer read _MaxSize;
  property RealSize: Integer read _RealSize;
  property DataType: TDataType read _DataType;
  procedure Output(Data : Pointer; MaxSize: Integer);
 end;

implementation

procedure TData.Init(MaxSize, DataType : Integer);
begin
 _MaxSize := MaxSize;
 _DataType := DataType;
 GetMem(_Data, _MaxSize);
end;

destructor TData.Destroy;
begin
 FreeMem(_Data);
end;

procedure TData.Input(Data : Pointer; DataSize : Integer);
begin
 if RealSize <= _MaxSize then
  begin
   _RealSize := DataSize;
   Move(Data, _Data, DataSize);
  end
 else
  ShowMessage('Speicherplatz überschritten!');
end;

procedure TData.Output(Data : Pointer; MaxSize: Integer);
begin
 if MaxSize >= _RealSize then
  Move(_Data, Data, _RealSize)
 else
  ShowMessage('Data zu klein!');
end;
Zitat:

Delphi-Quellcode:
D := TData.Create;
D.Init(500,1);

Mit Init als Constructor, würde dann
Delphi-Quellcode:
D := TData.Create(500, 1);
gehn.

Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
var
 arB : array of Byte;
 I,Len : Integer;
begin
 len := length(Edit1.Text);
 SetLength(arB, len);
 for I := 0 to len - 1 do
  arB[I] := ord(Edit1.Text[I+1]);
 D.Input(@arB[0], len);
end;

procedure TForm1.Button3Click(Sender: TObject);
var
 arB : TArByte;
 I : Integer;
begin
 SetLength(arB, D.RealSize); // D._RealSize ist PRIVAT ... sowas verwendet man nicht extern
 D.OutPut(@arB[0], Length(arB));
 for I := 0 to High(arB) do
  Caption := Caption + chr(arB[I]);
end;

Enumeratoren sind toll, erstmal ist somit alles logisch und physisch zusammen, was zusammen gehört
und die Quelltextvervollständigung verrät einem was man an soeine Variable/Parameter übergeben kann, da der Compiler nun auch weiß was zusammengehört.

Andre93 1. Sep 2011 23:16

AW: Delphi vergisst die Werte der Eigenschaften meiner Klasse
 
hey, danke dass ihr euch alle so viel mühe macht vorallem aber danke an himitsu. ihr helft mir alle wirklich ganz schön.

@himitsu,
das was du geschrieben hast leuchtet mir mittlerweile ein und ich verstehe jetzt auch warum meins falsch war..
was ich bloß noch mal fragen wollte ist :
ich dachte mir eigentlich es währe praktischer den speicher _data wirklich erst dann zu reservieren wenn man ihn braucht, also somit beim input. du hast den getmem()-befehl allerdings schon gleich bei init mit aufgerufen.
Delphi-Quellcode:
procedure TData.Init(MaxSize, DataType : Integer);
begin
 _MaxSize := MaxSize;
 _DataType := DataType;
 GetMem(_Data, _MaxSize); //das hier meine ich
end;
währe es nicht effizienter das im input zu machen? oder macht das so wie so keinen sinn und ist auch so wie so nicht umsetzbar??

außerdem wollte ich fragen ob du deinen änderungen am quelltext schon einmal getestet hast, denn ich hab damit das problem, dass nach dem output das array nicht die gesuchten werte sondern arB : [0,0,0,0,0] enthält.

himitsu 1. Sep 2011 23:29

AW: Delphi vergisst die Werte der Eigenschaften meiner Klasse
 
Wäre auch möglich, aber dann mußt du auch im Input prüfen, ob schon Speicher reserviert wurde, diesen Freigeben und kannst danach neuen Speicher reservieren.

PS: statt dem Pointer + RealSize könnte man intern ebenfalls ein array of Byte verwenden, dann kümmert sich Delphi um die Speicherverwaltung und abgesehn von dem SetLength in Input muß man sich um nichts mehr kümmern.

Es wird nichmal mehr viel mehr Speicher benötigt.
- die Array-Daten sind 8 Byte (Length + RefCount) größer und dafür Spart man 4 Byte (RealSize aka Length) in seiner Klasse ein (bei 32 Bit-Apps)

Andre93 6. Sep 2011 17:35

AW: Delphi vergisst die Werte der Eigenschaften meiner Klasse
 
soo..
also ich habe jetzt alles noch ein bisschen angepasst.
Ich hab jetzt alles auf array of Bytes aufgebaut und nicht mehr auf Pointern. außerdem habe ich den "getmem"-befehl in mein "input" gepackt damit der speicherplatz nur dann reserviert wird wenn er auch wirklich gebraucht wird. außerdem habe ich in meinem "input" jetzt noch eine abfrage mit drin, in der geprüft wird ob schon einmal daten hineingepackt wurden, sollte das der fall sein gebe ich den alten speicherbereich erst wieder frei bevor neuer reserviert wird.
und statt "init" habe ich jetzt "create" verwendet und die parameter angehängt.
allerdings wirft mein "Destroy" noch eine "invalid pointer operation" fehlermeldung und ich hab im moment noch keine idee warum.
da muss irgendwas an dem
Delphi-Quellcode:
FreeMem(_Data);
falsch sein



Delphi-Quellcode:
unit U_Data;

interface

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

type

TArByte = array of Byte;

TDataType = (dtNone, dtBool, dtByte, dtChar, dtString, dtInteger, dtReal);

TData = class
 private
  _Data, _TempData : TArByte;
  _MaxSize, _RealSize: Integer;
  _DataType : TDataType;
  _DataUsed : Boolean;
 public

  property MaxSize: Integer read _MaxSize;
  property RealSize: Integer read _RealSize;
  property DataType: TDataType read _DataType;
  property DataUsed: Boolean read _DataUsed;

  constructor Create(MaxSize : Integer; DataType : TDataType);
  destructor Destroy; override;

  procedure Input(Data : TArByte; DataSize : Integer);
  procedure Output(var Data : TArByte);

  //---

  procedure InputBool(B : Boolean);
  function OutputBool : Boolean;
  procedure InputInt(I : Integer);
  function OutputInt : Integer;
  procedure InputStr(S : String);
  function OutputStr : String;

 end;

implementation

constructor TData.Create(MaxSize : Integer; DataType : TDataType);
begin
 _MaxSize := MaxSize;
 _DataType := DataType;
 _DataUsed := False;
end;

destructor TData.Destroy;
begin
 FreeMem(_Data);
end;

procedure TData.Input(Data : TArByte; DataSize : Integer);
begin
 if RealSize <= _MaxSize then
  begin
   if DataUsed then
    FreeMem(_Data)
   else
    _DataUsed := true;
   _RealSize := DataSize;
   Move(Data, _Data, DataSize);
  end
 else
  ShowMessage('Speicherplatz überschritten!');
end;

procedure TData.Output(var Data : TArByte);
var
 I : Integer;
begin
 //For I := 0 to _RealSize - 1 do
  //Data[I] := _Data[I];
 Move(_Data, Data, _RealSize)
end;

//---

procedure TData.InputBool(B : Boolean);
begin

end;

function TData.OutputBool : Boolean;
begin

end;

procedure TData.InputInt(I : Integer);
begin

end;

function TData.OutputInt : Integer;
begin

end;

procedure TData.InputStr(S : String);
var
 I,Len : Integer;
begin
 len := length(S);
 SetLength(_TempData, len);
 for I := 0 to len - 1 do
  _TempData[I] := ord(S[I+1]);
 Input(@_TempData[0], len);
end;

function TData.OutputStr : String;
var
 I : Integer;
 S : String;
begin
 SetLength(_TempData, RealSize);
 OutPut(_TempData);
 for I := 0 to RealSize - 1 do
  S := S + chr(_TempData[I]);
 Result := S;
end;


end.

unit vom hauptprogramm
Delphi-Quellcode:
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Edit1: TEdit;
    Button4: TButton;
    GroupBox1: TGroupBox;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  D : TData;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
 D := TData.Create(500,dtString);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
 arB : array of Byte;
 I,Len : Integer;
begin
 len := length(Edit1.Text);
 SetLength(arB, len);
 for I := 0 to len - 1 do
  arB[I] := ord(Edit1.Text[I+1]);
 D.Input(@arB[0], len);

end;

procedure TForm1.Button3Click(Sender: TObject);
var
 arB : TArByte;
 I : Integer;
begin                                              
 SetLength(arB, D.RealSize);
 D.OutPut(arB);
 for I := 0 to D.RealSize - 1 do
  Caption := Caption + chr(arB[I]);
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
 D := TData.Create(500,dtString);
 D.InputStr(Edit1.Text);
 Caption := D.OutputStr;
 //D.Destroy; //führt zu invalid pointer operation
end;


end.

Andre93 19. Sep 2011 22:15

AW: Delphi vergisst die Werte der Eigenschaften meiner Klasse
 
hat noch irgendjemand einen tipp, warum das destroy nicht funktioniert?

Union 19. Sep 2011 22:20

AW: Delphi vergisst die Werte der Eigenschaften meiner Klasse
 
Wie wärs mit inherited Destroy in der letzten Zeile der Kompostierung?

himitsu 19. Sep 2011 22:39

AW: Delphi vergisst die Werte der Eigenschaften meiner Klasse
 
Man ruft Destroy nicht direkt auf :!:
Dafür gibt es Free.

Dynamische Arrays werden automatisch initialisiert und auch automatisch freigegeben.
> schmeiß das
Delphi-Quellcode:
FreeMem(_Data);
aus deinem Destructor raus.

A: dynamische Arrays werden eh nicht über FreeMem freigegeben :!:

B: wenn du es schon "so" freigibst, dann setze auch die Variable auf einen Zustand, welcher "freigegeben" bedeutet.
> nil ... aber nicht über
Delphi-Quellcode:
... := nil;
denn dieses würde Delphi verannlassen es freizugeben, was du ja schon gemacht hattest.


Grund für deinen Fehler:
- du versuchst das Array "falsch" feizugeben (welches vermutlich knallt)
- und selbst wenn das Freigeben funktionierte, dann versucht Delphi das nochmals, da es denkt es wäre nich nicht freigegeben, da du in der Variable den falschen Status (Pointer) zurückgelassen hattest, was dann auf jedenfall fehlschlagen würde.

Das ist so, als wenn man zweimal .Free auf eine Objektvariable aufrufen würde, ohne diese jeweils auf nil zu setzen.
Wobei Destroy nichtmal prüfen würde, womit es egal wäre es auf nil zu setzen, da es immer knallen würde.


Warum willst du überhaupt _Data an den vielen Stellen über FreeMem freigeben?
Hattest du es denn jemals über GetMem reserviert?


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