![]() |
Zugriffsverletzung beim Kürzen eines dyn. Arrays
Hallo,
ich habe mal wieder einen interessanten Fehler, bei dem ich mir eure Hilfe erhoffe. Beschreibung: In einem Programm werden Daten aus einem vorher erstellen dyn. Array ausgelesen. Ist das Auslesen abgeschlossen soll die entsprechende Zeile im dyn. Array gelöscht und das Array somit um ein Element gekürzt werden. Das klappt auch ganz gut, bis ich zum letzen Element (logischerweise Element 0) komme. Dann erhalte ich eine Zugriffsverletzung mit variablen Adressen. Das kürzendes Feldes erfolgt in einer Prozedur. Wenn ich die aus meinem Gesamtcode rausnehme läuft alles Problemlos, daher vermute ich den Fehler dort. Code der Prozedur:
Delphi-Quellcode:
Ich hoffe es hat jemand eine Idee, wie ich das Problem lösen kann. Danke schonmal!!!
procedure Loesche_Array_Element(const AIndex: Integer);
begin if Length(Feldplatz) = 1 then begin SetLength(Feldplatz, 0); // Länge kürzen //Feldplatz := nil; end else begin Move(Feldplatz[AIndex + 1], Feldplatz[AIndex], SizeOf(Feldplatz[0]) * (Length(Feldplatz) - AIndex - 1)); //Dahinterliegende Daten aufrücken SetLength(Feldplatz, Length(Feldplatz) - 1); // Länge kürzen end; end; |
AW: Zugriffsverletzung beim Kürzen eines dyn. Arrays
Was ist denn der Typ der Array-Elemente? Wenn da z.B. Strings drin sind, wird das mit dem Move so nicht funktionieren, weil du die Referenzzählung torpedierst.
|
AW: Zugriffsverletzung beim Kürzen eines dyn. Arrays
Hallo,
auch wenn dies nicht Deine Frage beantwortet.. Warum benutzt Du nicht die schon vorhanden Listen wie TStringList, TList oder TObjectList dor kannst Du problemlos etwas herauslöschen ohne das Du Dich darum kümmern musst die folgenden Elemente nachzurücken. Grüße Klaus |
AW: Zugriffsverletzung beim Kürzen eines dyn. Arrays
Das Array ist folgendermaßen aufgebaut:
Delphi-Quellcode:
Also funktionieren tut es insgesamt schon. Nur eben wenn AIndex 0 ist, bzw. das Feld die Länge 1 hat, tritt der Fehler auf.
Sortierung = Record
iRegalPlatz : Integer; // Regalplatz-Nr. iPosiPlatz : Integer; // Kistenplatz-Nr. im Regalplatz iKistePlatz : Integer; // Kisten-Nr. iStueckPlatz : Integer; // Stückzahl in der Kiste Datum : TDateTime; // Einlagerungsdatum Barcode : String; // Inhalt des Strings des Barcodes end; FeldPlatz : Array of Sortierung; @Klaus01: Das ist an sich eine Idee. Aber in diesem Zusammenhang und bei dem Umfang des Programms macht sich das nicht so gut. |
AW: Zugriffsverletzung beim Kürzen eines dyn. Arrays
Zitat:
|
AW: Zugriffsverletzung beim Kürzen eines dyn. Arrays
Zitat:
|
AW: Zugriffsverletzung beim Kürzen eines dyn. Arrays
Zitat:
Mit deiner "unsicheren" Umkopieroperation (und ohne korrekte Behandlung dieser Variablen/Typen) zerschießt du natürlich die Speicherverwaltung. Statt ![]() ![]()
Delphi-Quellcode:
verwenden.
String[123]
Außerdem sind Interfaces, Variants und andere dynamische Arrays ebenfalls verboten. |
AW: Zugriffsverletzung beim Kürzen eines dyn. Arrays
Ich danke für die Hilfe!
Kurzzeitgi hab ich das Problem jetzt erstmal so gelöst, dass ich bevor ich das Element lösche prüfe, ob das Feld nurnoch ein Element hat. Wenn das der Fall ist, dann unterlasse ich den Aufruf der Prozedur. Längerfristig gesehen werde ich den Code im Ganzen nochmal überarbeiten müssen. @Luckie: Mit einer "Begründung" kann ich zwar nicht dienen aber mit meiner persönlichen Einschätzung. :wink: Bisher war ich der Meinung, in der Stringlist wie der Name sagt, lediglich Strings handeln zu können. Dies würde bedeuten, dass ich alle Werte die ich in dem Record habe in Strings wandeln müsste und ggf. zurück. Dies ist bei der Vielzahl von Abfragen und Handlingfunktionen im Programm sehr aufwendig und unübersichtlich. |
AW: Zugriffsverletzung beim Kürzen eines dyn. Arrays
Zitat:
Ich weiß nicht wie gut in Delphi 2009 schon die Generics sind.. Wenn könnte man auch generische Listen verwenden.
Delphi-Quellcode:
Grüße
TFeldplatz = TList<TSortierung>;
Klaus |
AW: Zugriffsverletzung beim Kürzen eines dyn. Arrays
Wobei die Zugriffsverletzung nicht wegen dem gelöschten Element geschieht.
Dort baust du dir (so, wie du es machst) nur ein Speicherleck ein. Die Zugriffsverletzung kommt von dem letzen Element, in dem Array, denn das gibt es plötzlich zwei Mal. (Eines gibst du frei, beim kürzen des Arrays, und die vorhandene Kopie wird damit geschrottet) Vorm Verschieben müßte man das zu löschende Element freigeben (Finalize) dann verschieben, den letzen Eintrag (beim Löschen ... beim Einfügen der Erste an der Einfügestelle) nullen und danach die Arraygröße anpassen. Am Sichersten: - über eine Schleife jeden Eintrag einzeln vorziehen (den Record von Delphi kopieren lassen) und dann die Größe anpassen Oder man tauscht (mit binären Kopieroperationen, über einen "einfachen" Puffer, wie z.B. ein ByteArray) die Einträge aus. - zu Löschenden zwischenspeichern - verschieben - den letzen Eintrag überschreiben, mit dem Gespeicherten (ebenfall binär kopiert) - Arraygröße anpassen oder - zu Löschenden und letzen Eintrag austauschen (Idealer Weise über einen Zwischenspeicher vom selben Typen ... Delphi kopiert also) - Arraygröße anpassen |
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:14 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 by Thomas Breitkreuz