Delphi-PRAXiS
Seite 2 von 9     12 34     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Record zurücksetzen (löschen) (https://www.delphipraxis.net/120638-record-zuruecksetzen-loeschen.html)

Hansa 14. Sep 2008 12:27

Re: Record zurücksetzen (löschen)
 
Zitat:

Zitat von SubData
..dann werden aber die "Strings" da drin nicht wirklich überschrieben, sondern nur die Pointer, oder seh ich das jetzt falsch?

jo, ist falsch.

Neutral General 14. Sep 2008 12:28

Re: Record zurücksetzen (löschen)
 
Mh nee.. Ich glaube das siehst du richtig. Jetzt wo du's sagst... Muss man halt wirklich ne Record-Methode (seltsame Teile wie ich finde..) schreiben

Zitat:

Zitat von Hansa
Zitat:

Zitat von SubData
..dann werden aber die "Strings" da drin nicht wirklich überschrieben, sondern nur die Pointer, oder seh ich das jetzt falsch?

jo, ist falsch.

Ne ist richtig :stupid:

Guido Eisenbeis 14. Sep 2008 12:29

Re: Record zurücksetzen (löschen)
 
@Michael:
Danke für das "Entschrummpeln" der Forumsansicht! :thumb:


Zitat:

Zitat von Luckie
Oder besser noch, sag uns, was du eigentlich vor hast.

Zitat:

Zitat von sirius
Was heißt den löschen?

Record löschen, zurücksetzen, oder wie Marius schrieb "Alle Felder leeren", also alle Werte des Records auf einen Anfangswert setzen. Z. B. Strings auf '' (leer), Integer auf 0, ...

Was ich vorhabe:

Zum einen will ich hierbei meinen Delphi-Horizont erweitern. Bisher habe ich bei Records eine Routine geschrieben, in der alle Felder auf einen definierten Wert gesetzt wurden. Beispiel:

Delphi-Quellcode:

Type
  TMyRecord = record
    Test_1    : string;
    Test_2    : string;
    Integer_1 : Integer;
    Integer_2 : Integer;
  end;


function PrepareMsg(AMyRecord: TMyRecord): string;
begin
  Result :=
    'Test_1:   ' + AMyRecord.Test_1 + #13#10+
    'Test_2:   ' + AMyRecord.Test_2 + #13#10+
    'Integer_1:   ' + IntToStr(AMyRecord.Integer_1) + #13#10+
    'Integer_2:   ' + IntToStr(AMyRecord.Integer_2);
end;


procedure ResetMyRecord(var AMyRecord: TMyRecord);
begin
  AMyRecord.Test_1 := '';
  AMyRecord.Test_2 := '';
  AMyRecord.Integer_1 := 0;
  AMyRecord.Integer_2 := 0;
end;


procedure SetTestValues(var AMyRecord: TMyRecord);
begin
  AMyRecord.Test_1 := 'Hallo ';
  AMyRecord.Test_2 := 'Welt!';
  AMyRecord.Integer_1 := 9;
  AMyRecord.Integer_2 := 2008;
end;


procedure TForm1.Button1Click(Sender: TObject);
var
  MyRecord: TMyRecord;
begin
  // undefinierte AnfangsWerte (beim ersten Test erscheinen hier Zufallswerte)
  ShowMessage(PrepareMsg(MyRecord));

  // BeispielWerte zuweisen
  SetTestValues(MyRecord);
  ShowMessage(PrepareMsg(MyRecord));

  // mit "händischer" Lösung auf definierte AnfangsWerte setzen
  ResetMyRecord(MyRecord);
  ShowMessage(PrepareMsg(MyRecord));

  // BeispielWerte zuweisen
  SetTestValues(MyRecord);
  ShowMessage(PrepareMsg(MyRecord));

  // "FillChar"-Lösung
  Finalize(MyRecord);
  FillChar(MyRecord, SizeOf(MyRecord), 0);
  ShowMessage(PrepareMsg(MyRecord));
end;
Nun will ich zum Einen wissen, ob es da eine einfachere Möglichkeiten gibt, um meinen Code kürzer und übersichtlicher zu halten.
Zum Anderen hat die obige "händische" Lösung zwar den Vorteil, dass man selbst definierte Werte erhält, aber den Nachteil, dass das bei umfangreicheren Records schnell recht aufwendig wird. Hinzu kommt, dass in meinem konkretten Fall (Verknüpfungen auslesen) mein Record auch noch einen weiteren Record enthält. Da ist dann die Frage, wie weit die händische Lösung sinnvoll ist.

Delphi-Quellcode:
type
  TMyRecord = record
    Test_1    : string;
    Test_2    : string;
    Integer_1 : Integer;
    Integer_2 : Integer;
    FindData: TWIN32FINDDATA; // <-- weiterer Record in meinem Record
  end;

@toms

Die "MyBlankRecord"-Lösung entspricht in meiner Auffassung der "händischen" Lösung, ist hier also nicht gewollt.

Die "FillChar"-Lösung erscheint mir eher als eine Lösung in meinem Sinne. Gewünscht ist eine Lösung mit kurzem Code, die schon-vorhandene Delphi Routinen benutzt. Und das wäre hierbei der Fall. Und es schein sogar recht elegant zu sein.

OK, nach ersten Tests (siehe Komplett-Code oben) scheint die "FillChar"-Möglichkeit tatsächlich die gewünschte "elegange" Lösung zu sein. Ich werde nun noch Test mit dem zusätzlichen Record in meinem Record (FindDate: TWIN32FINDDATA) durchführen.


@Ronny
Meines Wissens nach werden mit FillChar auch die Strings auf "0" gesetzt (komplett mit Nullen gefüllt, also sozusagen Null-terminiert). Das entspricht einem leeren String und ist das gewünschte Ziel.

Mal sehen, was die anderen sagen. :-D

Guido.

Neutral General 14. Sep 2008 12:34

Re: Record zurücksetzen (löschen)
 
Hi,

Ein "Beweis", dass FillChar nicht funktioniert:
Delphi-Quellcode:
type
  TBeweis = packed record
    EinString: String;
    Zahl: Integer;
  end;

var Beweis: TBeweis;
    p: Pointer;
begin
  Beweis.EinString:= 'Test';
  p := @Beweis.EinString[1];
  FillChar(Beweis,SizeOf(TBeweis),0);
  ShowMessage(PChar(p));
end;
Dürfte dann übrigens ein schönes Speicherleck geben ;) (Außer der Memory-Manager räumt das trotzdem auf)
Wie SubData schon gesagt hat: Der Pointer zu dem eigentlichen String wird auf nil gesetzt. Aber der String selbst schwirrt noch im Speicher rum. Ist nur nichtmehr erreichbar, falls man den Pointer nicht vorher gesichert hat ;)

Hansa 14. Sep 2008 12:46

Re: Record zurücksetzen (löschen)
 
Liste der Anhänge anzeigen (Anzahl: 1)
Du beweist, dass man jedes noch so simple Problemchen derart verunstalten kann, dass es eventuell nicht mal richtig funktioniert. :mrgreen:

Delphi-Quellcode:
  MyRecord.nr := 1;
  MyRecord.name := 'XYZ';
  memo2.Lines.Add(IntToStr(MyRecord.nr));
  memo2.Lines.Add('*'+MyRecord.name+'*');
  memo2.Lines.Add('');
  FillChar (MyRecord,SizeOf (MyRecord),0);
  memo2.Lines.Add(IntToStr(MyRecord.nr));
  memo2.Lines.Add('*'+MyRecord.name+'*');
Das ergibt das im Anhang.

SubData 14. Sep 2008 12:47

Re: Record zurücksetzen (löschen)
 
Jap, so in etwa dachte ich mir das.
Finalize scheint aber auch nicht zu funktionieren.

Jedenfalls nicht, wenn das Record eine ThreadVar ist.
Zumindest meldet FastMM danach noch Speicherlecks.


Edit:

Zitat:

Zitat von Hansa
Du beweist, dass man jedes noch so simple Problemchen derart verunstalten kann, dass es eventuell nicht mal richtig funktioniert. :mrgreen:

Delphi-Quellcode:
  MyRecord.nr := 1;
  MyRecord.name := 'XYZ';
  memo2.Lines.Add(IntToStr(MyRecord.nr));
  memo2.Lines.Add('*'+MyRecord.name+'*');
  memo2.Lines.Add('');
  FillChar (MyRecord,SizeOf (MyRecord),0);
  memo2.Lines.Add(IntToStr(MyRecord.nr));
  memo2.Lines.Add('*'+MyRecord.name+'*');
Das ergibt das im Anhang.

Damit beweist du nur, dass der Pointer auf den eigentlichen String nicht mehr existiert.
Ob der String damit aber wirklich freigegeben wurde, wird daraus nicht deutlich.

SubData 14. Sep 2008 12:49

Re: Record zurücksetzen (löschen)
 
Edit: Kann weg...

Neutral General 14. Sep 2008 12:50

Re: Record zurücksetzen (löschen)
 
Natürlich steht dann in MyRecord.Name nichts mehr. Weil der String "genilt" wurde. Aber der String selbst liegt immernoch im Speicher rum.

SubData 14. Sep 2008 12:51

Re: Record zurücksetzen (löschen)
 
Und ich wette FastMM würde rumnörgeln ;-)

Edit: Michael: Magste das mal mit FastMM testen?

Hansa 14. Sep 2008 12:54

Re: Record zurücksetzen (löschen)
 
Zitat:

Zitat von Neutral General
..Aber der String selbst liegt immernoch im Speicher rum.

Da liegt noch viel mehr rum. In diesem speziellen Fall gehe ich allerdings davon aus, dass tatsächlich die Variable anderen Wert bekommt und nicht extra neu angelegt wird. Bei einem Record handelt es sich nunmal NICHT um Pointer etc.


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:09 Uhr.
Seite 2 von 9     12 34     Letzte »    

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