Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Access Violation bei SetLength
der organist - Di 24.02.09 18:54
Titel: Access Violation bei SetLength
Hi Leutz,
ich hab keine Idee mehr, woran es liegen kann.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| type TSpieler=Class private public Insel:Record Koord:Array of TPoint; Name:Array of String; end; Punkte,ID:Integer; Name:String; constructor Create(AName:String;APunkte,AID:Integer); procedure AddIsland(AKoord:TPoint;AName:String); procedure DeleteIsland(AKoord:TPoint;AName:String); End; |
Delphi-Quelltext
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:
| procedure TSpieler.AddIsland(AKoord: TPoint; AName: String); var k: Integer; Name,Koord:Boolean; begin Name:=true; Koord:=true; if Length(Insel.Koord)>0 then begin for k := 0 to Length(Insel.Koord) - 1 do begin if Insel.Name[k]=AName then Name:=false; if (Insel.Koord[k].X=AKoord.X) AND (Insel.Koord[k].Y=AKoord.Y) then Koord:=false; end; end; if Name AND Koord then begin SetLength(Insel.Koord,Length(Insel.Koord)+1); SetLength(Insel.Name,Length(Insel.Name)+1); Insel.Koord[Length(Insel.Koord)-1].X:=AKoord.X; Insel.Koord[Length(Insel.Koord)-1].Y:=AKoord.Y; Insel.Name[Length(Insel.Name)-1]:=AName; end else if (NOT Name) AND (NOT Koord) then ShowMessage('Koordinaten sind schon unter diesem Name eingetragen') else if (NOT Name) AND Koord then ShowMessage('Name existiert schon mit anderen Koordinaten') else ShowMessage('Koordinaten existieren schon unter anderem Inselnamen'); end; |
überall, wo ich Insel.Koord aufrufe, gibt es ne Violation, da kann ich die eine auskommentieren, dann stehts halt beim nächsten mal.
Des Weiteren ist dies nicht die erste Version des Quelltextes. Zuvor hatte ich, anstatt die Länge des Koordinaten-Arrays zu zählen, eine Variable "Anzahl", im Record definiert, was allerdings den selben Fehler hervorruft.
Außerdem lässt sich sagen, dass beim ersten Mal Insel hinzufügen, keine Violation auftritt; Erst, wenn ich eine zweite hinzufügen will, gibts Probleme.
MfG,
Xentar - Di 24.02.09 20:02
1. Instanziierst du die Klasse auch, wenn du sie benutzt? Zeig mal den Aufruf..
2. Warum ein Record, bestehend aus 2 Arrays? Wenn beide zusammengehören, mach doch lieber ein array of record.
3. Äh.. wieso deklarierst du das Record IM Public Bereich? Ich kenn das eigentlich nur so, dass man einen Type erstellt, und diesen dann nur noch verwendet.
der organist - Di 24.02.09 20:06
ok, ich seh' die Lösung zwar noch nicht, aber:
zu 1. Was meinst du damit? Ob ich den Spieler auch created hab?
zu 2. Hab noch nie drüber nachgedacht, aber wie mach ich das? Wo defnier ich das Record um danach ein Array daraus zu
machen? (Quelltext erwünscht..)
zu 3. Naja, Hobbyprogrammierung eben, hab nie Unterricht drin gehabt und außerdem greife ich regelmäßig in anderen Units
drauf zu...
MfG,
Xentar - Di 24.02.09 20:11
der organist hat folgendes geschrieben : |
ok, ich seh' die Lösung zwar noch nicht, aber:
zu 1. Was meinst du damit? Ob ich den Spieler auch created hab?
|
Richtig.
Zu den anderen Sachen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| Type TInsel = Record Koord: TPoint; Name: String; end; TInseln = array of TInsel;
TSpieler = class ....... Inseln: TInseln; |
der organist - Di 24.02.09 20:16
Ok, das mit dem Inselrecord, das ist iwie besser, werde mich dann mal auf viele Änderungen einstellen, wenn ich im Interface-Teil etwas ändere.....aber ich probiere es aus.
Ja, den Spieler hab ich Created und die erste Insel "erschaffen" funzt auch richtig, die zweite will nicht mehr.
der organist - Di 17.03.09 20:19
*push* Problem tritt immer noch auf und stört momentan wirklich
(a) Hab mir ein Record angelegt
(b) ich hab mal alles auskommentiert, was nicht den Fehler verursacht, Problemzeile hab ich markiert
(c) Wenn ich bei Spieler A eine Insel hinzufüge, dann bei Spieler B und dann wieder bei A, dann gibt es keine Probleme, nur wenn ich nacheinander zwei bei Spieler A hinzufügen will.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| Type TInsel=Record Koord: TPoint; Name: String; end; TSpieler=Class private ..... public Insel:Array of Tinsel; ..... end; |
Delphi-Quelltext
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:
| procedure TSpieler.AddIsland(AKoord: TPoint; AName: String); var k: Integer; TName,TKoord:Boolean; begin SetLength(Insel,Length(Insel)+1); end; |
Xentar - Di 17.03.09 20:53
Zeig mal mehr Code.. also, wie du die Spieler erzeugst, wo du die Methode AddIsland aufrufst, usw.
Yogu - Di 17.03.09 21:34
Ich glaube, du hast vergessen, eine Instanz von TSpieler zu erstellen, nach der Fehlermeldung und dem wenigen Code zu urteilen.
dummzeuch - Di 17.03.09 22:48
Yogu hat folgendes geschrieben : |
| Ich glaube, du hast vergessen, eine Instanz von TSpieler zu erstellen, nach der Fehlermeldung und dem wenigen Code zu urteilen. |
Das glaube ich auch. Vermutlich der Klassiker:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| var Spieler: TSpieler; begin Spieler.Create;
Spieler := TSpieler.Create; |
Passiert mir peinlicherweise auch immer wieder mal.
twm
Boldar - Di 17.03.09 22:50
Ich glaube, dass gibt aber schon eine Fehlermeldung beim Compilieren...
Xentar - Di 17.03.09 22:53
Boldar hat folgendes geschrieben : |
| Ich glaube, dass gibt aber schon eine Fehlermeldung beim Compilieren... |
Nö, nur eine Warnung.
| Zitat: |
| [DCC Warnung] W1036 Variable 'blah' ist möglicherweise nicht initialisiert worden |
und es gibt genug Leute, die eine Warnung nicht ernst nehmen..
dummzeuch - Di 17.03.09 22:57
Xentar hat folgendes geschrieben : |
Boldar hat folgendes geschrieben : | | Ich glaube, dass gibt aber schon eine Fehlermeldung beim Compilieren... |
Nö, nur eine Warnung.
| Zitat: | | [DCC Warnung] W1036 Variable 'blah' ist möglicherweise nicht initialisiert worden |
und es gibt genug Leute, die eine Warnung nicht ernst nehmen.. |
Und diese Warnung gibt es nicht, wenn die Variable vorher mal initialisiert wurde, z.B. durch Zweisung von NIL oder wenn es sich um ein Feld einer Klasse handelt.
twm
der organist - Mi 18.03.09 19:58
Für die Ungläubigen (nehmts mir nich übel):
Instanzierung vom Spieler:
Delphi-Quelltext
1: 2: 3: 4:
| SetLength(Player,Length(Player)+1); Player[Length(Player)-1]:=TSpieler.Create(Name, StrToInt(Punkte), Length(Player)-1); |
Das ganze sieht ein wenig chaotisch aus, weil ich ein Array of TSpieler hab.
Aufrufen von AddIsland:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7:
| procedure TDialogAddIsland.AddClick(Sender: TObject); begin UMain.Main.Player[Players.Itemindex].AddIsland(Point(StrToInt(Koord1.Text), StrToInt(Koord2.Text)), IslandName.Text); ReFill; end; |
Ist mehr gewünscht? Kann auch alle Units kopieren :D .....aber das dürfte dann doch zu viel sein.
Yogu - Mi 18.03.09 20:16
Hallo,
bitte benutze, um das oberste Element eines dynamischen Arrays zu bekommen, die Funktion High anstatt Length(Arr)-1. Das dürfte aber nicht das Problem sein, da dynamische Arrays für gewöhnlich bei Null beginnen.
Zur Fehlersuche: Schau mal, ob in der Funktion AddClick UMain.Main.Player[Players.Itemindex] assigned ist. Und ob es auf eine gültige Instanz zeigt. Dazu könntest du ein einfaches privates Feld der Klasse erstellen (vom Typ Integer oder so), und auf es zugreifen. Sollte dort auch eine Zugriffsverletzung kommen, liegt es sicher daran.
Noch was: initialisierst du die dynamischen Arrays im Konstruktor? Du solltest SetLength(Arr, 0); aufrufen, um den Pointer erstmal richtig zu setzen.
Grüße,
Yogu
der organist - Mi 18.03.09 20:24
Was meinst du mit assigned? Hab noch nie was davon gehört, also von vorne erklären...
Yogu - Mi 18.03.09 20:28
der organist hat folgendes geschrieben : |
| Was meinst du mit assigned? Hab noch nie was davon gehört, also von vorne erklären... |
Ich meinte, ob das Objekt
nil ist, oder ob es exisitert. Einfach mal ein Haltepunkt an eine günstige Stelle setzen und mit der Maus über den Namen fahren, dann siehst du entweder eine Adresse (das ist gut) oder
nil (dann hast du was falsch gemacht).
der organist - Mi 18.03.09 20:33
z.B. ich bewege die Maus über dsa Itemindex aus myCombobox.Itemindex. Bei mir erscheint dann:
Property
System.Integer
(oder so ähnlich...)
ich ersetze mal das Players.itemindex durch ne konstante und schau ob es daran liegt.
Xentar - Mi 18.03.09 20:40
der organist hat folgendes geschrieben : |
z.B. ich bewege die Maus über dsa Itemindex aus myCombobox.Itemindex. Bei mir erscheint dann:
Property
System.Integer |
Er meint zur Laufzeit (Haltepunkt setzen - F5)
der organist - Mi 18.03.09 20:46
ok, hab ich gemacht. wenn ich dann z.B. über UMain gehe, dann wird ne Box angezeigt, mit ner Menge wirrwarr, die ich mir nicht lange angetan habe, bei dem Itemindex nicht. (Hat auch mit auskommentieren und durch Konstante ersetzten gefunzt... :D )ok, was mach ich jetzt?
Was ich noch gefunden habe ist:
Wenn ich die ReFill-prozedur nicht aufrufe, dann funzt es:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7:
| procedure TDialogAddIsland.AddClick(Sender: TObject); begin UMain.Main.Player[Players.Itemindex].AddIsland(Point(StrToInt(Koord1.Text), StrToInt(Koord2.Text)), IslandName.Text); ReFill; end; |
und das ist die ReFillprozedur:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| procedure TDialogAddIsland.ReFill; var k:Integer; begin IslandName.Text:='IslandName'; Koord1.Text:='Koord:X'; Koord2.Text:='Koord:Y'; Players.Items.Clear; for k := 0 to Length(UMain.Main.Player)-1 do begin UDialogAddIsland.DialogAddIsland.Players.Items.Add(UMain.Main.Player[k].Name); end; end; |
und ich glaube, mir ist gerade jetzt der Fehler aufgefallen:
Beim neufüllen der Combobox wird der Itemindex wieder auf (-1) oder was weiss ich gesetzt, und ein Player[-1] gibbet es natürlich nicht.
EDIT: DAS WARS LEUTE!!! Wir haben ihn gefunden. Danke allen, die sich hier die Mühe gemacht haben und dann die Anstöße gebracht haben.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!