![]() |
String freigeben nur wo?
Mein Problem ist leider immer noch nicht gelöst. :oops:
EurekaLog! Zitat:
FBuffin Wenn ich im Dialog von EurekaLog doppelkicke dann geht er mir in diese Zeile.
Delphi-Quellcode:
Das Problem ist nur, ich weis nicht wo ich ihn freigeben soll.
try
try while not eof(ParseFile) do begin ReadLN(ParseFile, sBuffer); AppendToLinkedList(nReading, sBuffer); // sBuffer soll einen Memoryleak produzieren. inc(nReading); end; except raise Exception.Create(SysErrorMessage(GetLastError)); end; finally nReading := 0; CloseFile(ParseFile); end; Theoretisch würde ich es so machen.
Delphi-Quellcode:
Nur dann lösche ich den String im Array dieser ist dann auch '' obwohl ich den String erst nach der Übergabe lösche.
while not eof(ParseFile) do
begin ReadLN(ParseFile, sBuffer); AppendToLinkedList(nReading, sBuffer); // sBuffer soll einen Memoryleak produzieren. inc(nReading); // String freigeben nachdem er übergeben wurde ZeroMemory(Pointer(sBuffer), Length(sBuffer) * SizeOf(Char)); sBuffer := ''; end;
Delphi-Quellcode:
Keine Ahnung wo ich den String sonst freigeben soll wenn nicht an angezeigter Position.
procedure AppendToLinkedList(nReading: Integer; sBuffer: string);
begin New(FPBuffer); if nReading = 0 then Begin New(FToPBuffer); LineStart := FToPBuffer; LineStart^.Nr := 0; end; FPBuffer^.Nr := nReading; FPBuffer^.Str := sBuffer; //<< der ist dann nachdem löschen von sBuffer leer LineStart^.Max := FPBuffer^.Nr; FToPBuffer^.Ptr := FPBuffer; FToPBuffer := FPBuffer; end; Edit: Hier das gleiche!
Delphi-Quellcode:
siehe Shot.. Doppelklick auf FormatINI dann springt er in diese Zeile.
procedure FormatINI(Filename: string);
var sBuffer: string; ParseFile: TextFile; StringList: TStringList; StringParse: string; procedure AppendToLinkedList(nReading: Integer; sBuffer: string); begin New(FPBuffer); if nReading = 0 then Begin New(FToPBuffer); LineStart := FToPBuffer; LineStart^.Nr := 0; end; FPBuffer^.Nr := nReading; FPBuffer^.Str := sBuffer; LineStart^.Max := FPBuffer^.Nr; FToPBuffer^.Ptr := FPBuffer; FToPBuffer := FPBuffer; end; begin StringList := TStringList.Create; Assignfile(ParseFile, Filename); reset(ParseFile); try try while not eof(ParseFile) do begin ReadLN(ParseFile, sBuffer); AppendToLinkedList(nReading, sBuffer); inc(nReading); end; except raise Exception.Create(SysErrorMessage(GetLastError)); end; finally nReading := 0; CloseFile(ParseFile); end; FPBuffer := LineStart; while (FPBuffer.Nr <= LineStart.Max - 1) do begin FPBuffer := FPBuffer.Ptr; StringParse := LeftTrim(FPBuffer.Str); if Length(StringParse) <> 0 then StringList.Add(FPBuffer^.Str); if FPBuffer.Nr > 0 then if LeftStr(FPBuffer^.Str, 1) = '[' then StringList.Insert(StringList.IndexOf(StringParse), ''); ZeroMemory(PWideChar(FPBuffer.Str), Length(FPBuffer.Str) * SizeOf(Char)); FPBuffer.Str := ''; end; StringList.SaveToFile(Filename); StringList.Free; Dispose(FPBuffer); FPBuffer := nil; LineStart := nil; end;
Delphi-Quellcode:
AppendToLinkedList(nReading, sBuffer);
gruss |
AW: String freigeben nur wo?
Das ZeroMemory ist hier wohl eher schädlich, da es die Referenzzählung der Strings umgeht. Ein Finalize(FPBuffer^) sollte da verträglicher sein.
Was mir auffällt ist, daß für jede Zeile im AppendToLinkedList ein New() aufgerufen wird, es aber nur ein einziges Dispose() gibt. Außerdem vermisse ich die Initialisierung von nReading mit 0. |
AW: String freigeben nur wo?
Zitat:
Zitat:
Delphi-Quellcode:
FPBuffer^.Nr := nReading;
Nun das ist schon gegeben.. nReading ist 0 beim start. Aber ich kann es noch ändern wobei ich aber denke das es nicht nötig ist. Wenn ich eine Variable als integer definiere dann ist automatisch wenn nichts anderes angegeben wird der erste wert = 0 oder liege ich da falsch? In dem Fall muss ich nReading nicht extra 0 zuweisen. Aber wenn das für dich besser ist? Kein Problem.
Delphi-Quellcode:
gruss
try
try nReading := 0; while not eof(ParseFile) do begin ReadLN(ParseFile, sBuffer); AppendToLinkedList(nReading, sBuffer); inc(nReading); end; except raise Exception.Create(SysErrorMessage(GetLastError)); end; finally CloseFile(ParseFile); end; |
AW: String freigeben nur wo?
Zitat:
|
AW: String freigeben nur wo?
Zitat:
Ich würde es aber in jedem Fall vor der while-Schleife setzen, denn dann könnte man die procedure auch mehrmals aufrufen. In dem Code habe ich sonst nur das Freigeben der Strings entfernt und eine Schleife zum Freigeben der linked List eingebaut. Vielleicht ist das MemoryLeak damit ja schon behoben.
Delphi-Quellcode:
procedure FormatINI(Filename: string);
var sBuffer: string; ParseFile: TextFile; StringList: TStringList; StringParse: string; procedure AppendToLinkedList(nReading: Integer; sBuffer: string); begin New(FPBuffer); if nReading = 0 then Begin New(FToPBuffer); LineStart := FToPBuffer; LineStart^.Nr := 0; end; FPBuffer^.Nr := nReading; FPBuffer^.Str := sBuffer; LineStart^.Max := FPBuffer^.Nr; FToPBuffer^.Ptr := FPBuffer; FToPBuffer := FPBuffer; end; begin StringList := TStringList.Create; Assignfile(ParseFile, Filename); reset(ParseFile); try try nReading := 0; while not eof(ParseFile) do begin ReadLN(ParseFile, sBuffer); AppendToLinkedList(nReading, sBuffer); inc(nReading); end; except raise Exception.Create(SysErrorMessage(GetLastError)); end; finally nReading := 0; CloseFile(ParseFile); end; FPBuffer := LineStart; while (FPBuffer.Nr <= LineStart.Max - 1) do begin FPBuffer := FPBuffer.Ptr; StringParse := LeftTrim(FPBuffer.Str); if Length(StringParse) <> 0 then StringList.Add(FPBuffer^.Str); if FPBuffer.Nr > 0 then if LeftStr(FPBuffer^.Str, 1) = '[' then StringList.Insert(StringList.IndexOf(StringParse), ''); end; StringList.SaveToFile(Filename); StringList.Free; { linked List freigeben } while LineStart <> nil do begin FPBuffer := LineStart; LineStart := FPBuffer.Ptr; { Bei Dispose kümmert sich der Compiler um das Finalize } Dispose(FPBuffer); end; { keine dangling Pointer hinterlassen } FPBuffer := nil; FToPBuffer := nil; end; |
AW: String freigeben nur wo?
danke dir Uwe..
Ich habe es vorher mal so versucht.
Delphi-Quellcode:
Ist das gleiche Ergebnis wie bei dir.
if not Assigned(FPBuffer) then
New(FPBuffer); //..... finalize(FPbuffer^); Dispose(FPBuffer); FPBuffer := nil; finalize(LineStart^); Dispose(LineStart); LineStart := nil; Ich bin darauf gekommen weil du sagtest Zitat:
Doch ist nötig ;) Deshalb nehme ich deine Lösung. Danke noch mal. Beide Varianten melden jetzt keinen Speicherleck mehr. Frage mich nur warum beim doppelklick in dem EurekaLog Dialog auf diese zeile gesprungen wird.
Delphi-Quellcode:
AppendToLinkedList(nReading, sBuffer); // sBuffer soll einen Memoryleak produzieren.
das irritiert doch etwas denn sBuffer kann ich dort nicht einfach löschen. Zitat:
gruss |
AW: String freigeben nur wo?
Zitat:
BTW, warum überhaupt eine linked List? Eine TList<PassenderRecordTyp> ist doch viel einfacher zu handhaben. Das Ptr Feld im Record wäre dann auch obsolet. Zitat:
Eurekalog kann aber nur erkennen, wo der Speicher alloziert wurde und das ist eben in dieser Zeile. |
AW: String freigeben nur wo?
Sorry Uwe war vorschnell geurteilt ;)
Habe es editiert. Zitat:
Zitat:
gruss |
AW: String freigeben nur wo?
Zitat:
|
AW: String freigeben nur wo?
Zitat:
Habe es nun mal so gemacht. Und mit Uwes Hilfe wird jetzt alles korrekt frei gegeben. Danke nochmals. gruss |
AW: String freigeben nur wo?
Hmm.. musste es doch nochmal ändern.
Es funktioniert nur beim ersten mal wird die gleiche Funktion nochmals aufgerufen dann kracht es mit invaliden Pointer.
Delphi-Quellcode:
so geht's.
{ linked List freigeben }
while LineStart <> nil do begin FPBuffer := LineStart; LineStart := FPBuffer.Ptr; { Bei Dispose kümmert sich der Compiler um das Finalize } Dispose(FPBuffer); end; { keine dangling Pointer hinterlassen } FPBuffer := nil; FToPBuffer := nil;
Delphi-Quellcode:
finde den Fehler bei deiner Variante leider nicht.
Count := LineStart.Max;
for i := 0 to Count do begin FPBuffer := LineStart; LineStart := FPBuffer.Ptr; Dispose(FPBuffer); end; Dispose(LineStart); FPBuffer := nil; FToPBuffer := nil; LineStart := nil; gruss |
AW: String freigeben nur wo?
Warum benutzt du nicht einfach PChar für Strings, die du selber verwalten willst? Oder, meinetwegen, WideString.
Denn "String" ist halt referenzgezählt und wird selber erzeugt und freigegeben. Bei "PChar" hast du auch schon "StrNew" und "StrDispose". |
AW: String freigeben nur wo?
[QUOTE=Dennis07;1425881]Warum benutzt du nicht einfach PChar für Strings, die du selber verwalten willst? Oder, meinetwegen, WideString.QUOTE]
Weil ich es nun mal auf string ausgelegt habe und ja die sind auch Unicodefähig zumindest ab Delphi 2009 glaube ich. Und im Grunde genommen sind Strings in Delphi schon mächtig. Warum soll ich mich dann mit PChar (PWideChar) rumschlagen wenn es auch so geht. Sorry aber ich habe keine Lust jetzt meine Library deshalb wieder komplett umzumodeln. Für Außenstehende ist das einfach zu erfragen warum machst du das nicht so oder so. ;) Zitat:
selbst freigegeben.. nein sonst müsste ich mir nicht die Arbeit machen oder? gruss |
AW: String freigeben nur wo?
Zitat:
Delphi-Quellcode:
Reicht völlig aus.
...
sBuffer := ''; Strings verhalten sich wie Interfaces, Stringvariablen wie Interfacevariablen. Ein String belegt einen bestimmten Speicherbereich, fällt der Referenzzähler des Strings auf 0, wird dieser an den Speichermanager als frei gemeldet. (Das heist nicht das der Speichermanager diesen auch sofort an Windows frei gibt oder mit Nullen überschreibt.) Wird ein String sowohl einer Variablen als auch einer Liste zugewiesen, wird trotzdem nur einmal Speicher belegt. Nur der Referenzzähler erhöht sich bei jeder Zuweisung. Wird der Speicherbereich gelöscht, verweisen natürlich auch beide auf den gelöschten Speicher. Das ist natürlich nicht erwünscht. |
AW: String freigeben nur wo?
Zitat:
Eben nicht! Denn so hatte ich es vorher weil ich das auch angenommen habe. Aber! ![]() Wenn meine vorherige Herangehensweise den String zu löschen richtig ist\wäre dann taugt EurekaLog nichts :) gruss |
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:02 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