AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Zugriffsverletzung beim Kürzen eines dyn. Arrays
Thema durchsuchen
Ansicht
Themen-Optionen

Zugriffsverletzung beim Kürzen eines dyn. Arrays

Ein Thema von roadrunner-S51 · begonnen am 25. Jan 2012 · letzter Beitrag vom 25. Jan 2012
Antwort Antwort
Seite 1 von 2  1 2      
roadrunner-S51

Registriert seit: 28. Mai 2010
53 Beiträge
 
Delphi 2009 Professional
 
#1

Zugriffsverletzung beim Kürzen eines dyn. Arrays

  Alt 25. Jan 2012, 11:27
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:
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;
Ich hoffe es hat jemand eine Idee, wie ich das Problem lösen kann. Danke schonmal!!!
  Mit Zitat antworten Zitat
Benutzerbild von uligerhardt
uligerhardt

Registriert seit: 19. Aug 2004
Ort: Hof/Saale
1.746 Beiträge
 
Delphi 2007 Professional
 
#2

AW: Zugriffsverletzung beim Kürzen eines dyn. Arrays

  Alt 25. Jan 2012, 11:38
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.
Uli Gerhardt
  Mit Zitat antworten Zitat
Klaus01
Online

Registriert seit: 30. Nov 2005
Ort: München
5.768 Beiträge
 
Delphi 10.4 Sydney
 
#3

AW: Zugriffsverletzung beim Kürzen eines dyn. Arrays

  Alt 25. Jan 2012, 11:46
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
Klaus

Geändert von Klaus01 (25. Jan 2012 um 11:50 Uhr)
  Mit Zitat antworten Zitat
roadrunner-S51

Registriert seit: 28. Mai 2010
53 Beiträge
 
Delphi 2009 Professional
 
#4

AW: Zugriffsverletzung beim Kürzen eines dyn. Arrays

  Alt 25. Jan 2012, 11:48
Das Array ist folgendermaßen aufgebaut:

Delphi-Quellcode:
  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;
Also funktionieren tut es insgesamt schon. Nur eben wenn AIndex 0 ist, bzw. das Feld die Länge 1 hat, tritt der Fehler auf.

@Klaus01: Das ist an sich eine Idee. Aber in diesem Zusammenhang und bei dem Umfang des Programms macht sich das nicht so gut.
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#5

AW: Zugriffsverletzung beim Kürzen eines dyn. Arrays

  Alt 25. Jan 2012, 11:56
@Klaus01: Das ist an sich eine Idee. Aber in diesem Zusammenhang und bei dem Umfang des Programms macht sich das nicht so gut.
Das musst du mir jetzt aber mal begründen. Es reduziert den Code. Es macht den Code stabiler. Du kannst dich auf das hauptsächliche Problem konzentrieren.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von uligerhardt
uligerhardt

Registriert seit: 19. Aug 2004
Ort: Hof/Saale
1.746 Beiträge
 
Delphi 2007 Professional
 
#6

AW: Zugriffsverletzung beim Kürzen eines dyn. Arrays

  Alt 25. Jan 2012, 12:01
Das Array ist folgendermaßen aufgebaut:

Delphi-Quellcode:
  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;
Also funktionieren tut es insgesamt schon. Nur eben wenn AIndex 0 ist, bzw. das Feld die Länge 1 hat, tritt der Fehler auf.
Und du hast nicht $H-/$LONGSTRINGS OFF, d.h. Barcode ist ein referenzgezählter Typ? Dann verursacht das Move Probleme, selbst wenn du sie nicht sofort um die Ohren geknallt kriegst. Überleg mal: Angenommen Feldplatz hat noch zwei Elemente und du rufst Loesche_Array_Element(0) auf. Dann wird der Record Feldplatz[1] auf Feldplatz[0] ge-move-t, d.h. Feldplatz[0].Barcode und Feldplatz[1].Barcode verweisen auf den gleichen String, haben aber trotzdem nur Referenzzähler 1. Beim nachfolgenden Aufruf von SetLength wird Feldplatz[1] finalisiert, was insbesondere den Referenzzähler von Feldplatz[1].Barcode dekrementiert und, da 0 rauskommt, den String entsorgt. Dummerweise zeigt Feldplatz[0].Barcode jetzt auf einen freigegebenen Speicherbereich. Das kracht nicht zwangsweise sofort, ist aber trotzdem übel.
Uli Gerhardt
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.071 Beiträge
 
Delphi 12 Athens
 
#7

AW: Zugriffsverletzung beim Kürzen eines dyn. Arrays

  Alt 25. Jan 2012, 12:02
Zitat:
String
Bei diesen Typen verwaltet Delphi den Speicherplatz.
Mit deiner "unsicheren" Umkopieroperation (und ohne korrekte Behandlung dieser Variablen/Typen) zerschießt du natürlich die Speicherverwaltung.

Statt Delphi-Referenz durchsuchenString könntest du einen Delphi-Referenz durchsuchenShortString (Länge 255), bzw. einen ShortString mit Längenangabe String[123] verwenden.

Außerdem sind Interfaces, Variants und andere dynamische Arrays ebenfalls verboten.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.

Geändert von himitsu (25. Jan 2012 um 12:05 Uhr)
  Mit Zitat antworten Zitat
roadrunner-S51

Registriert seit: 28. Mai 2010
53 Beiträge
 
Delphi 2009 Professional
 
#8

AW: Zugriffsverletzung beim Kürzen eines dyn. Arrays

  Alt 25. Jan 2012, 12:43
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.
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.
  Mit Zitat antworten Zitat
Klaus01
Online

Registriert seit: 30. Nov 2005
Ort: München
5.768 Beiträge
 
Delphi 10.4 Sydney
 
#9

AW: Zugriffsverletzung beim Kürzen eines dyn. Arrays

  Alt 25. Jan 2012, 12:50
@Luckie: Mit einer "Begründung" kann ich zwar nicht dienen aber mit meiner persönlichen Einschätzung.
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.
.. nun man muss ja für Records nicht unbedingt eine StringListe hernehmen.
Ich weiß nicht wie gut in Delphi 2009 schon die Generics sind..

Wenn könnte man auch generische Listen verwenden.

TFeldplatz = TList<TSortierung>; Grüße
Klaus
Klaus
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.071 Beiträge
 
Delphi 12 Athens
 
#10

AW: Zugriffsverletzung beim Kürzen eines dyn. Arrays

  Alt 25. Jan 2012, 12:53
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
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.

Geändert von himitsu (25. Jan 2012 um 13:07 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:26 Uhr.
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