![]() |
Re: Record zurücksetzen (löschen)
Hallo,
Zitat:
![]() Gruß Hawkeye |
Re: Record zurücksetzen (löschen)
ups :oops:
Hab aber nicht abgeschrieben, ehrlich :oops: |
Re: Record zurücksetzen (löschen)
Liste der Anhänge anzeigen (Anzahl: 1)
Bei verschachtelten Records läuft das genauso.
Delphi-Quellcode:
Ergebnis : Anhang. In diesem Beispiel ist auch das Finalize völlig überflüssig.
MyRecord : record
nr : Integer; name : string [10]; MyRecord2 : record nr : Integer; name : string [10]; end; end; procedure TForm1.FormCreate(Sender: TObject); begin MyRecord.nr := 1; MyRecord.name := 'XYZ'; MyRecord.MyRecord2.nr := 2; MyRecord.MyRecord2.name := 'XYZ2'; 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+'*'); memo2.Lines.Add(IntToStr(MyRecord.MyRecord2.nr)); memo2.Lines.Add('*'+MyRecord.MyRecord2.name+'*'); end; |
Re: Record zurücksetzen (löschen)
Hatten wir nicht gerade, dass bei globalen Variablen mit der Methode ein MemoryLeak auftritt ?!
|
Re: Record zurücksetzen (löschen)
Zitat:
Zitat:
|
Re: Record zurücksetzen (löschen)
Hallo,
noch einmal zur Klarstellung: Bei referenzgezählten Daten (dynamische Strings und Arrays, Interfaces) sollte ein Aufruf von Finalize vorgeschaltet werden, damit die internen Verwaltungsinformationen aufgeräumt werden können. Der Compiler erzeugt dabei einen Aufuf der zugehörigen RTL-Routine, die selbst feststellen kann, welche Felder des Records finalisiert werden müssen. Dies sollte mit beliebig geschachtelten Datentypen funktionieren. "Einfache" Zeiger werden von Finalize nicht zerstört. Bei Referenzen auf Speicherbereiche oder Objekte ist der Programmierer selbst für die Freigabe der referenzierten Objekte verantwortlich. Hierzu wird die komplementäre Routine (GetMem/FreeMem, Create/Free,...) aufgerufen, um den Speicher wieder freizugeben. Einfache Datentypen (Ordinaltypen, Fließkommatypen, kurze Strings(!),...) benötigen keine Aufräumarbeiten. Ein Aufruf von FillChar darf erst erfolgen, nachdem die Verwaltungsdaten ordnungsgemäß aufgeräumt wurden. Beachtet man dies nicht, entstehen Memory Leaks. Gruß Hawkeye |
Re: Record zurücksetzen (löschen)
Zitat:
Delphi-Quellcode:
Und das Ding soll leergemacht werden. Wozu dann soviel Klimbim machen ? Von der Compiler-Direktive $H+ ist nichts zu sehen. Insofern ist das finalize überflüssig und wird sogar vom Linker entfernt.
type
TMyRecord = record Test_1: string; Test_2: string; Test_3: string; Integer_1: integer; Integer_2: integer; end; ... MyRecord: TMyRecord; |
Re: Record zurücksetzen (löschen)
String ist nicht gleich String[10], das ist der Unterschied.
|
Re: Record zurücksetzen (löschen)
Moin Hansa,
Zitat:
Ausserdem sind Huge-Strings auch die Standardeinstellung. Hast Du es bei Dir umgestellt? ;-) |
Re: Record zurücksetzen (löschen)
Zitat:
|
Re: Record zurücksetzen (löschen)
Hi,
Zitat:
Mfg FAlter |
Re: Record zurücksetzen (löschen)
Zitat:
Zitat:
Natürlich wird der String auch ohne Finalize zu einem Leerstring. Allerdings hinterlässt du ein MemoryLeak. Du machst quasi folgendes:
Delphi-Quellcode:
Ich denke du siehst, dass obiger Code ein MemoryLeak verursacht. Richtig wäre es so:
var pc: PChar;
begin GetMem(pc,6); // mit PChar arbeiten pc := nil; // = FillChar(String,SizeOf(String),0); end;
Delphi-Quellcode:
Ich hoffe, du hast jetzt verstanden worum es geht. Im Endeffekt ist pc immer nil. Das Ergebnis ist scheinbar das Gleiche.
var pc: PChar;
begin GetMem(pc,6); // mit PChar arbeiten FreeMem(pc); // Finalize(RecordmitString); pc := nil; // = FillChar(RecordmitString,SizeOf(TRecordmitString),0); end; |
Re: Record zurücksetzen (löschen)
Hm. :gruebel:
also Records sind ja sowieso nicht mehr ganz OOP konform. Gerad ein so einen Fall bieten sich klassen an, da Klassen Daten und Methoden die Daten zu manipulieren kapseln. Da würde ich dann eine Methode Init schreiben, die die Attribute auf einen definierten Wert setzt. Was passiert eigentlich mit String Attributen, wenn man des Objekt auf nil setzt? |
Re: Record zurücksetzen (löschen)
Zitat:
|
Re: Record zurücksetzen (löschen)
Das ist ja Müll.
|
Re: Record zurücksetzen (löschen)
Was hast du denn erwartet/gehofft? :gruebel:
|
Re: Record zurücksetzen (löschen)
Dass der MemoryManager erkennt, dass es sich um Strings handelt und den Speicher entsprechend freigibt.
|
Re: Record zurücksetzen (löschen)
So... Und ich hab da auch mal was nettes:
Folgendes Konstrukt:
Delphi-Quellcode:
Am Anfang des Threads werden alle Felder gefüllt bzw. irgendwann im laufenden Thread.
type
TThreadVars = record sServerHost : String; sRemoteIP : String; sPHPSession : String; sVar1 : String; sVar2 : String; sVar3 : String; sVar4 : String; sVar5 : String; dVar1 : TDateTime; iVar1 : Int64; (* --- Request Infos --- *) pThread : ^TIdContext; pRequest : ^TIdHTTPRequestInfo; pResponse : ^TIdHTTPResponseInfo; end; threadvar tv : TThreadVars; Am Ende des Threads wird folgendes aufgerufen:
Delphi-Quellcode:
Und was passiert?
Finalize(tv);
FillChar(tv, SizeOf(tv), 0); Richtig, ich hab ein Memory Leak. Allerdings nur in den ersten 3 String Variablen. Wenn ich diese per Hand auf zurücksetze ( var := ''; ) dann ist das Memory Leak weg... |
Re: Record zurücksetzen (löschen)
Zitat:
Zitat:
Zitat:
Da reicht ein nil setzen volkomen aus, und der Memorymanager(/GC) kümmert sich um den Rest ;) Zum Thema: Eine Klasse wäre natürlich praktischer. Dann kannst du auch direkt die Klasse Thread-Safe implementieren und alles sollte klappen :stupid: |
Re: Record zurücksetzen (löschen)
@All
OK, ... ich ... schreibe ... jetzt ... mal ... sehr ... langsam und lasse mir Zeit, bevor ich diese Posting losschicke. Ich will mich eigentlich schon die ganze Zeit bedanken für die rege Beteiligung und die wirklich guten Infos. Aber jedes Mal wenn ich ansetze, um dies zu schreiben kommen in der Zwischenzeit wieder neue Beiträge. ;-) Ihr seid richtig flott! Ich bin erfreut und beeindruckt, was hier eine rege Diskussion entstanden ist. Ich habe an einem bestimmten Punkt gedacht, dass die FillChar-Möglichkeit eine Lösung für das Thema meines Threads ist. Dann kamen neue Infos und ich begann über die Speicherlecks zu grübeln. Dann war wieder alles klar, und nach einigen weiteren Post gings von vorne los. Ich träume schon von Speicherlecks! :cyclops: Nun habe ich mich entschieden, dass die FillChar-Lösung die richtige für mein Problem ist und werde sie verwenden. Ich habe auch ein kleines Demo dazu geschrieben. Das fasst zwar im Prinzip nur die hier geposteten Infos zusammen, aber wenn Interesse besteht, werde ich das Demo gerne hier posten. Ansonsten freue ich mich auch weiterhin über Infos, die zu diesem Thema beitragen! :P Guido. |
Re: Record zurücksetzen (löschen)
Zitat:
|
Re: Record zurücksetzen (löschen)
Zitat:
|
Re: Record zurücksetzen (löschen)
Hier das Demo:
Delphi-Quellcode:
Beispiel:
unit Unit2;
(* ============================== Record-Variable schnell leeren ============================== Um alle Felder einer Record-Variablen schnell und einfach zu leeren, kann man die Routinen "Finalize" + "FillChar" benutzen. Diese wurden in diesem Demo in der Prozedur "Clear" zusammengefasst. Dabei werden String-Variablen auf leer, Zahlen-Variablen auf Null, ... gesetzt. Auch verschachtelte Records können damit geleert werden. Das heißt, Records die selbst wieder Records enthalten. In der Methode Clear müssen vor dem abschließenden FillChar-Befehl alle (dynamischen) Daten im Record freigegeben werden. Finalize selbst berücksichtigt nur die referenzgezählten Daten. Speicherbereiche, die mit New o. ä. angelegt wurden, sowie Objekte, die durch Aufruf eines Konstruktors erzeugt wurden, muss man also auch wieder manuell freigeben. Tipp von Hawkeye219 auf [url]www.delphipraxis.net[/url], in meinem Thread "Sonstige Fragen zu Delphi \ Record zurücksetzen (löschen)". Forum-Thread und Demo von Guido Eisenbeis, 2008-09-14. *) interface uses Windows; Type TMyRecord = record Test_1 : string; Test_2 : string; Integer_1 : Integer; Integer_2 : Integer; FindData: TWIN32FINDDATA; procedure Clear(); end; implementation // Finalize + FillChar Lösung procedure TMyRecord.Clear(); begin Finalize(Self); FillChar(Self, SizeOf(Self), 0); end; end. ----------
Delphi-Quellcode:
Guido.
unit Unit1;
... implementation {$R *.dfm} uses Unit2; // Einige Testwerte setzen procedure SetTestValues(var AMyRecord: TMyRecord); begin AMyRecord.Test_1 := 'Hallo'; AMyRecord.Test_2 := 'Welt!'; AMyRecord.Integer_1 := 9; AMyRecord.Integer_2 := 2008; AMyRecord.FindData.cFileName := 'TestVal'; end; // String für Ausgabe formatieren 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) + #13#10+ 'FindData.cFileName: ' + '>' + AMyRecord.FindData.cFileName + '<'; 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)); // Alle Record-Felder mit "FillChar" leeren. MyRecord.Clear; ShowMessage(PrepareMsg(MyRecord)); // Beispielwerte zur Kontrolle erneut zuweisen SetTestValues(MyRecord); ShowMessage(PrepareMsg(MyRecord)); end; |
Re: Record zurücksetzen (löschen)
Zitat:
noch auf speicherbereiche in denen der "müll" von anderen anwendungen rumliegt. naja soweit glaube ich es verstanden zu haben. mfg smallsmoker |
Re: Record zurücksetzen (löschen)
Zitat:
|
Re: Record zurücksetzen (löschen)
Hallo smallsmoker, willkommen in der Runde. :-D
Hab ich mich da nicht deutlich genug ausgedrückt ? :gruebel: Zitat:
Zitat:
Somit haben wir beide das Gleiche gesagt, nur anders ausgedrückt. Ich dachte, dass Programmierer das so interpretieren. :P Guido. |
Re: Record zurücksetzen (löschen)
Zufallswerte sind nicht undefinierte Werte.
Da gibt es riesige Unterschiede, aber das würde das Thema hier sprengen ;-) |
Re: Record zurücksetzen (löschen)
Zitat:
Guido. |
Re: Record zurücksetzen (löschen)
Zitat:
|
Re: Record zurücksetzen (löschen)
Und?
|
Re: Record zurücksetzen (löschen)
Nix und, ich wollte nur darauf hinweisen, dass Zufallswerte und undefinierte Werte nicht das Gleiche sind :)
|
Re: Record zurücksetzen (löschen)
Bin über die Funktion "ZeroMemory" gestolpert. Wenn man die anstatt "FillChar" benutzt, hat das Vor- oder Nachteile?
Guido. |
Re: Record zurücksetzen (löschen)
Soweit ich weiß, macht das keinen Unterschied.
|
Re: Record zurücksetzen (löschen)
Zitat:
Delphi-Quellcode:
procedure ZeroMemory(Destination: Pointer; Length: DWORD);
begin FillChar(Destination^, Length, 0); end; |
Re: Record zurücksetzen (löschen)
hab zwar nicht den gesamten thread gelesen, aber bei der methode finalize/zeromemory, sollt man vorsichtig sein. wenn man so etwas anwendet muss man immer einen konkreten record im hinterkopf haben, sonst bekommt man die schönsten speicherlöcher ... :drunken:
|
Re: Record zurücksetzen (löschen)
Zitat:
Das ist ja der Hammer und die Frage hat sich somit erledigt! *lol* Vielen Dank euch beiden! Guido. |
Re: Record zurücksetzen (löschen)
Ich nutze Delphi2005Prof und möchte myrecord.clear() (s.o.) nutzen.
Beim compilieren erhalte ich: "E2029 'END' erwartet, aber 'PROCEDURE' gefunden". Der Cursor steht in Unit 2 hinter dem Wort procedure der Tmyrecord deklaration. Type TMyRecord = record Test_1 : string; Test_2 : string; Integer_1 : Integer; Integer_2 : Integer; FindData: TWIN32FINDDATA; procedure Clear(); end; Sind spezielle Units einzubinden oder wird es in der Delphi-Version nicht unterstützt? |
Re: Record zurücksetzen (löschen)
Diese Möglichkeit hast Du leider erst ab Delphi 2006.
|
Re: Record zurücksetzen (löschen)
Danke für die schnelle Antwort.
|
Re: Record zurücksetzen (löschen)
Wäre es möglich, eine compilierte Unit2 unter D2006 mit D2005 zu nutzen?
D. h. Bearbeitung der Unit1 unter D2005 und Zugriff auf die dcu (mit dem Record) vom D2006? Wenn ja, gilt das auch für folgende Delphi-Versionen? |
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:12 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz