![]() |
Delphi-Version: 2010
A/V bei löschen von Element in Array
Hallo,
ich habe eine eigene StringListen Klasse für Plugin-DLLs geschrieben, damit ich Classes nicht einbinden muss (und sie somit nicht so aufgebläht werden). Die Liste bietet außerdem einige Extra-Funktionen, z.B. einen Filter darauf anzuwenden, d.h. alle Elemente die Filter nicht enthalten werden gelöscht.
Delphi-Quellcode:
Das ganze basiert auf einem array of string (FArray), Count gibt einfach nur Length(FArray) aus. Das Problem ist, dass nach einem Durchlauf der Speicher irgendwie korrumpiert wird, denn plötzlich tauchen im Array noch andere Strings die irgendwo in der DLL vorkommen auf und irgendwann ist es dann so kaputt, dass eine A/V geworfen wird.
procedure TCSList.ApplyFilter(F: string);
var i: Integer; begin for i := 0 to Count - 1 do if Pos(F, FArray[i]) = 0 then if i = Count - 1 then SetLength(FArray, Count - 1) else begin Move(FArray[i + 1], FArray[i], (Count - 1 - i) * 4); // String = 4 Byte Pointer SetLength(FArray, Count - 1); ApplyFilter(F); // Count geändert, Schleife neustarten Exit; end; end; Vielleicht mögen die String-Pointer es nicht rumgeschoben zu werden? Ich konnte den Fehler nicht finden :( |
AW: A/V bei löschen von Element in Array
Wenn du die Stringreferenzen nicht korrekt behandelt, dann muß es ja probleme geben.
der String, welchen du "angelich" löschts ... da überschreibst du nur den "Zeiger", aber der String selber bleibt als Speicherleck zurück. Und als Ausgleich hast du durch dein Move auch noch den letzen String im Array mit einer doppelten Referenz, welcher aber nicht in der Referenzzählung auftaucht, womit der dann schon freigegeben wird, aber dennoch in der Liste steht ... taj, beim nächsten Zugriff darauf, da muß es einfach knallen. Mein Tipp: verwende eine echte Stringliste, statt des Arrays ... so sehr aufblähen tut soeine Liste auch nicht und du mußt nicht an der Referenzzählung rumfummeln. Ansonten mußt du die Zeiger halt korrekt behandeln, also manuell auf nil, bzw. einen Leerstring setzen. |
AW: A/V bei löschen von Element in Array
Zitat:
Delphi-Quellcode:
. Dies hat den Vorteil, dass der Compiler auch weiß, was du machen willst und sich demnach richten kann.
FArray[i] := FArray[i + 1]
Bernhard |
AW: A/V bei löschen von Element in Array
So, habe jetzt vor dem Move
Delphi-Quellcode:
das hinzugefügt.
FArray[i] := ''; // Zu löschenden freigeben
Jetzt läuft der Code ohne Probleme durch, aber wie kann ich die doppelte Referenz verhindern? Der letzte Pointer steht dann ja kurzfristig 2x in der Liste (bis SetLength die Liste verkleinert), aber wenn ich den hinteren auf leer setze betrifft das ja auch den vorletzten. @rollstuhlfahrer: Strings sind Zeiger auf Arrays, das "Array" selbst steht woanders. |
AW: A/V bei löschen von Element in Array
Hab ich mir auch noch nie Gedanken gemacht. Ich hätte gleich die Delete()-Funktion der Stringliste aufgerufen. So hätte ich mit Denkaufwand und Redundanz gespart.
Bernhard |
AW: A/V bei löschen von Element in Array
Delphi-Quellcode:
Aber, wie gesagt, nimm lieber eine Stringliste .. diese ist nur unwesentlich größer, der Overhead ist minimal und man erspart sich viel Arbeit und eventuelle Probleme und nur ein Delete(i) wäre auch verständlicher.
FArray[i] := '';
Move(FArray[i + 1], FArray[i], (Count - 1 - i) * SizeOf(Pointer)); Pointer(FArray[Count - 1]) := nil; SetLength(FArray, Count - 1); Und vorallem, wenn man nciht genau weiß was man macht und warum, ist es eh keine gute Idee Automatismen (wie die delphiinterne Speicherverwaltung/Referenzzählung) zu manipulieren. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:52 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