| Autor |
Beitrag |
Martello
      
Beiträge: 131
WIN 2000
TP, C, Delphi 1.0, Turbo Delphi 2006, Delphi 7
|
Verfasst: Sa 14.08.10 13:17
Ich habe zufällig auch ein Problem mit dyn. Arrays, die ich zum ersten Mal verwende.
typ gegend = array of record...
Ich möchte Daten aus einer *.csv-Datei in ein Feld einlesen und dann verwenden.
Die dyn. Länge wurde korrekt gesetzt, und die strukturierten Daten aus der Input-Datei-Text wurden meiner Meinung nach auch korrekt eingelesen. Wenn ich aber auf diese Daten zugreifen möchte, tritt jedesmal eine Zugriffsverletzung auf:
wenn Index 0: Fehlermeldung bei Adresse 00000000
..Index 1: ..bei Adresse 00000020
..Index 2: ..bei Adresse 00000040
..Index 3: ..bei Adresse 00000060
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42:
| procedure lade_gegend(filename:string; Umfeld:Gegend); var inn: text; i,j: integer; row: string; zeile: Tstringlist;
begin i:=0; assign(inn,filename); reset(inn); zeile:= Tstringlist.create;
repeat readln(inn); i:=i+1; until eof(inn); reset(inn); setlength(umfeld,i); geof_int:=i;
for j:= 0 to i-1 do
begin readln(inn,row); zeile.delimitedtext:=row; showmessage(zeile[4]); with umfeld[j] do begin
Name:= zeile[0]; Zeit:= strtoint(zeile[1]); lat:= strtofloat(zeile[2]); lon:= strtofloat(zeile[3]);; dir:= strtoint(zeile[4]);
end;
end; umfeld:=nil;
close(inn); end; |
Weil es sich intern um Zeiger handelt, habe ich am Ende umfeld:=nil eingefügt. Aber meine Erfahrungen mit Zeigern sind genauso nichtig wie die mit dyn. Arrays
Hat jemand eine Idee, wo der Fehler liegen könnte?
Gruß
Martello
|
|
Gausi
      
Beiträge: 8554
Erhaltene Danke: 481
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Sa 14.08.10 13:54
Du setzt am Ende den übergebenen Parameter auf Nil, d.h. du investierst viel Arbeit, das "Umfeld" zu füllen, und pfefferst dann das Ganze ins Nirvana, indem du das auf Nil setzt.
Ich würde das Umfeld := Nil einfach mal weglassen.  Wenn das nicht hilft: Wo genau tritt denn der Fehler auf?
_________________ We are, we were and will not be.
|
|
Martello 
      
Beiträge: 131
WIN 2000
TP, C, Delphi 1.0, Turbo Delphi 2006, Delphi 7
|
Verfasst: Sa 14.08.10 16:04
Gausi hat folgendes geschrieben : |
Ich würde das Umfeld := Nil einfach mal weglassen. Wenn das nicht hilft: Wo genau tritt denn der Fehler auf? |
Mir war das auch suspekt; an der Stelle passiert die damit gemeinte Speicherplatzfreigabe tatsächlich um einiges zu früh.
Aber der Fehler liegt leider woanders.
Während der Typ meines dyn- Arrays in einer eigenen UNIT deklariert wird, vereinbare ich in meiner UNIT1 (Form1) eine Variable mit dem Namen "Areal". Die Datenübergabe von der Datei nach Areal funktioniert von dort aus fehlerfrei. Das anschließende Anzeigen via Button5Klick führt dann aber zu der Fehlermeldung.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| procedure TForm1.Button5Click(Sender: TObject); var i:integer; begin i:=strtoint(edit9.text); edit9.Text:=areal[i].Name; edit10.Text:=inttostr(areal[i].zeit); edit11.Text:=floattostr(areal[i].lat); edit12.Text:=floattostr(areal[i].lon); edit13.Text:=inttostr(areal[i].dir); end; |
Der Fehler kommt mir sehr bekannt vor: Bei meinen ersten Versuchen mit Zeigern trat er auch ständig auf, weil ich versucht hatte auf nicht initialisierte Bereiche zuzugreifen. Daher verzichte ich in meinem Projekt zu nächst auch auf Zeiger und verwende stattdessen testweise erst mal ein dyn. Array für meine Zwecke. Aber intern werden dyn. Arrays - wie ich gelesen habe - wie Pointer verwaltet; irgendwo in der Gegend dürfte daher der Fehler zu finden sein.
Ich habe das dyn. Array testweise zu einem statischen umfunktioniert. Dabei zeigt sich, dass beim Datenauslesen nichts
"herauskommt", die Editfelder 9 bis 13 bleiben leer. Die Zugriffsverletzung tritt nicht mehr auf.
Aber ein anderer Fehler erscheint, der wahrscheinlich mit dem ersten verwandt ist. Warum funktioniert das Dateneinlesen, nicht aber das Auslesen aus meiner "Matrix" alias Array of Record?
Gruß
Martello
Zuletzt bearbeitet von Martello am Sa 14.08.10 16:18, insgesamt 1-mal bearbeitet
|
|
Gausi
      
Beiträge: 8554
Erhaltene Danke: 481
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Sa 14.08.10 16:13
Hat areal wirklich soviele Einträge, d.h. hast du SetLength passend (also mit Länge i+1) vorher aufgerufen? Wie ist areal definiert, lokal, global, al Eigenschaft der Form? Ist das evtl. sogar doppelt deklariert und du greifst auf das "falsche" Array zu?
_________________ We are, we were and will not be.
|
|
Martello 
      
Beiträge: 131
WIN 2000
TP, C, Delphi 1.0, Turbo Delphi 2006, Delphi 7
|
Verfasst: Sa 14.08.10 16:34
Gausi hat folgendes geschrieben : | | Hat areal wirklich soviele Einträge, d.h. hast du SetLength passend (also mit Länge i+1) vorher aufgerufen? Wie ist areal definiert, lokal, global, al Eigenschaft der Form? Ist das evtl. sogar doppelt deklariert und du greifst auf das "falsche" Array zu? |
Ich habe Areal als letzte Variable var areal.gegend; unmittelbar vor "implementation"definiert.
Gefüllt (also "initialisiert") wird sie durch Klick auf Form1:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| procedure TForm1.Button2Click(Sender: TObject);
begin lade_gegend('c:\ort\ampeln.csv',areal); edit1.Text:=inttostr(geof_int);
end; |
Sie wird also in Form1 vereinbart und dort auch zweimal aufgerufen. Beim ersten Aufruf verwende ich eine Procedure, ("lade_gegend") die in einer anderen unit2 vereinbart ist; aber daran sollte es eigentlich nicht liegen...Meine Testdatei besteht nur aus drei Zeilen; setlength wurde mit 3 korrekt berechnet (siehe meinen ersten Post) , daran liegt es also auch nicht
Gruß
Martello
|
|
SvenAbeln
      
Beiträge: 334
Erhaltene Danke: 3
|
Verfasst: Sa 14.08.10 16:34
|
|
Martello 
      
Beiträge: 131
WIN 2000
TP, C, Delphi 1.0, Turbo Delphi 2006, Delphi 7
|
Verfasst: Sa 14.08.10 16:47
SvenAbeln hat folgendes geschrieben : | Wenn du die Werte auch außerhalb der Prozedur benutzen willst, musst du mit einem VAR Parameter arbeiten.
In deiner Ursprünglichen Funktion gibt es auch noch ein Memory Leak, es fehlt am Ende noch ein:
Delphi-Quelltext
|
Ein grober Pascal-Anfängerfehler, der mir sicher auch vor Jahrzehnten bereits passiert ist....
Vielen Dank für die Korrektur.
Und mit
Delphi-Quelltext
ist das Programm sogar ein wenig eleganter, wohingegen die Speicherbereiche des Arrays nie freizugeben sind, denn ich brauche sie ja schließlich bis zum Programm-Ende.
Aber hätte umfeld:=nil; nicht doch auch Speicherplatz wieder zu Verfügung gestellt, allein dadurch, dass die intern für das Feld verwendete Variable nicht länger auf Speicher sondern ins Nichts zeigt?
Gruß
Martello
|
|
Gausi
      
Beiträge: 8554
Erhaltene Danke: 481
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Sa 14.08.10 16:51
Mit umfeld := nil gibst du keinen Speicher frei, sondern kehrst den Datenmüll nur unter den Teppich, wo ihn keiner mehr sieht. Das geht solange gut, bis der Speicher voll ist, bzw. der Teppich wegen des ganzen druntergekehrten Mülls an der Decke klebt.
Wenn du ein Objekt mit Free freigibst, dann bringst du den Müll runter in die Tonne und hast wieder Platz in deinem Zimmer.
_________________ We are, we were and will not be.
|
|
elundril
      
Beiträge: 3747
Erhaltene Danke: 123
Windows Vista, Ubuntu
Delphi 7 PE "Codename: Aurora", Eclipse Ganymede
|
Verfasst: Sa 14.08.10 16:55
Seit wann muss man eigentlich Records mit Free freigeben? Wie ich noch unter D3/D5 gelernt habe musste man das nicht, sondern konnte das Ding wie ne Integer oder String einfach im Raum herumkugeln lassen?
lg elundril
_________________ This Signature-Space is intentionally left blank.
Bei Beschwerden, bitte den Beschwerdebutton (gekennzeichnet mit PN) verwenden.
|
|
Gausi
      
Beiträge: 8554
Erhaltene Danke: 481
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Sa 14.08.10 16:58
Jup, aber oben wird eine TStringlist "Zeile" erzeugt. Und die muss man mit .free freigeben. 
_________________ We are, we were and will not be.
|
|
elundril
      
Beiträge: 3747
Erhaltene Danke: 123
Windows Vista, Ubuntu
Delphi 7 PE "Codename: Aurora", Eclipse Ganymede
|
Verfasst: Sa 14.08.10 17:01
oh, mein Fehler, ich dachte es ist noch immer das Record gemeint.  Ich setz mich jetzt dann mal in ne Ecke, bin still und schäm mich n bissl.
_________________ This Signature-Space is intentionally left blank.
Bei Beschwerden, bitte den Beschwerdebutton (gekennzeichnet mit PN) verwenden.
|
|
Martello 
      
Beiträge: 131
WIN 2000
TP, C, Delphi 1.0, Turbo Delphi 2006, Delphi 7
|
Verfasst: Sa 14.08.10 17:04
elundril hat folgendes geschrieben : | Seit wann muss man eigentlich Records mit Free freigeben? Wie ich noch unter D3/D5 gelernt habe musste man das nicht, sondern konnte das Ding wie ne Integer oder String einfach im Raum herumkugeln lassen?
lg elundril |
Vektor:=nil habe ich aus einem wunderschönen Delphi-Buch, das ich für 1 Euro bei ebay erstanden habe. Dort wird Delphi in knapper Form sehr gut von 3 kompetenten Autoren beschrieben. Auch alles was ich persönlich über dyn. Arrays weiß, steht dort. Irgendwie leuchtet das mit "Speicher wieder freigeben" ein, wenn man sich veranschaulicht, dass dyn. Arrays intern als Pointer verwaltet werden.
Gruß
Martello
|
|
|