| Autor |
Beitrag |
morvister
Hält's aus hier
Beiträge: 15
XP
Delphi 2005 Prof.
|
Verfasst: Di 05.08.08 19:56
Hallo liebe Leutz!
Ich plage mich derzeit mit einem Problem beim Füllen eines dyn. Arrays. Möglicherweise ein typischer OOP-Falsch-DenkFehler (bin neu in der OOP, hab beruflich hauptsächlich mit Cobol zu tun - hey, hier wird nicht gelacht!  )
Nun zum Code:
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: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, Unit2;
type TSpiel = class(TObject) Owner: String[20]; Port: Integer; AnzSpielerGes: Byte; AnzSpielerFrei: Byte; private public end;
TForStart = class(TForm) Panel1: TPanel; Button1: TButton; Button2: TButton; Panel2: TPanel; Label1: TLabel; Panel3: TPanel; Button3: TButton; Button4: TButton; procedure Button4Click(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure FormActivate(Sender: TObject); procedure Button1Click(Sender: TObject); procedure Button3Click(Sender: TObject); private public Port: Integer; AnzSpieler: Integer; Spielername: String[20]; arrSpiele: array of TSpiel; end;
var ForStart: TForStart; Spiel: TSpiel;
implementation
{$R *.dfm}
procedure TForStart.Button1Click(Sender: TObject); var i: Integer; begin Form2.ShowModal; if (Spielername <> '') then begin Spiel := TSpiel.Create; Spiel.Port := Port; Spiel.AnzSpielerGes := AnzSpieler; Spiel.Owner := Spielername;
i := High(arrSpiele); if i < 0 then i := 0; arrSpiele[i] := Spiel; Spiel.Free; end;
end; |
An der markierten Zeile bricht mir das PGM mit einer EAccessViolation ab. Sehr ärgerlich  Hat das mit dem handling von i, oder dem handling des arrays, oder der definition desselbigen zu tun?
Die Variablen ForStart.Port, -.AnzSpieler und -.Spielername werden aus Form2 heraus gefüllt. Hier Form2:
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: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56:
| unit Unit2;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls;
type TForm2 = class(TForm) Button1: TButton; Button2: TButton; Edit1: TEdit; Panel1: TPanel; Label1: TLabel; Label2: TLabel; ComboBox1: TComboBox; Label4: TLabel; Edit2: TEdit; procedure Edit2KeyPress(Sender: TObject; var Key: Char); procedure Button2Click(Sender: TObject); procedure Button1Click(Sender: TObject); private public function PortAdressePruefen: Boolean; function SpielernamePruefen: Boolean; end;
var Form2: TForm2;
implementation
uses Unit1; {$R *.dfm}
procedure TForm2.Button1Click(Sender: TObject); var ok: boolean; begin ok := SpielerNamePruefen;
if ok then PortAdressePruefen;
if ok then begin ForStart.Port := StrToInt(Edit1.Text); ForStArt.AnzSpieler := StrToInt(ComboBox1.Text); ForStart.Spielername := Edit2.Text; end;
Close; end; |
Ich wäre für eure Hilfe wahnsinnig dankbar. Ich möchte möglichst schnell fit werden in Delphi um dem Forum auch mal als Berater und nicht nur als Fragender zu neuen Beiträgen zu verhelfen
Vielen Dank schon mal
morvi
|
|
Marc.
      
Beiträge: 1876
Erhaltene Danke: 129
Win 8.1, Xubuntu 15.10
|
Verfasst: Di 05.08.08 20:08
Momentan hat Dein dyn. Array eine Länge von Null. Mit Setlength(); kannst Du die Anzahl der Elemente festlegen.
cu
Marc.
|
|
wirbeldelphi
      
Beiträge: 29
|
Verfasst: Di 05.08.08 20:09
Dein Array hat wohl die Größe Null solange du die nicht mit SetLength geändert hast. Zugriffe auf das erste Element werden da wohl nix.
SetLength(arrSpiele, neueArrayGröße);
_________________ Ich bin keine Signatur - ich putz hier nur.
|
|
morvister 
Hält's aus hier
Beiträge: 15
XP
Delphi 2005 Prof.
|
Verfasst: Di 05.08.08 20:11
Nachtrag:
Mir ist noch aufgefallen, dass ich Spiel.AnzSpielerFrei noch gar nicht gefüllt hatte und hab das bereinigt. Außerdem hab ich mal versucht, die Felder einzeln von Spiel ins arrSpiele zu packen. Bringt auch nix. Hier der aktuelle Code:
(nur die procedure, in der das Array versorgt wird, denn nur die hab ich geändert):
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:
| procedure TForStart.Button1Click(Sender: TObject); var i: Integer; begin Form2.ShowModal; if (Spielername <> '') then begin Spiel := TSpiel.Create; Spiel.Port := Port; Spiel.AnzSpielerGes := AnzSpieler; Spiel.AnzSpielerFrei := AnzSpieler; Spiel.Owner := Spielername;
i := High(arrSpiele); if i < 0 then i := 0; arrSpiele[i].Owner := Spiel.Owner; arrSpiele[i].Port := Spiel.Port; arrSpiele[i].AnzSpielerGes := Spiel.AnzSpielerGes; arrSpiele[i].AnzSpielerFrei := Spiel.AnzSpielerFrei; Spiel.Free; end;
end; |
|
|
Boldar
      
Beiträge: 1555
Erhaltene Danke: 70
Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
|
Verfasst: Di 05.08.08 20:11
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: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, Unit2;
type TSpiel = class(TObject) Owner: String[20]; Port: Integer; AnzSpielerGes: Byte; AnzSpielerFrei: Byte; private public end;
TForStart = class(TForm) Panel1: TPanel; Button1: TButton; Button2: TButton; Panel2: TPanel; Label1: TLabel; Panel3: TPanel; Button3: TButton; Button4: TButton; procedure Button4Click(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure FormActivate(Sender: TObject); procedure Button1Click(Sender: TObject); procedure Button3Click(Sender: TObject); private public Port: Integer; AnzSpieler: Integer; Spielername: String[20]; arrSpiele: array of TSpiel; end;
var ForStart: TForStart; Spiel: TSpiel;
implementation
{$R *.dfm}
procedure TForStart.Button1Click(Sender: TObject); var i: Integer; begin Form2.ShowModal; if (Spielername <> '') then begin Spiel := TSpiel.Create; Spiel.Port := Port; Spiel.AnzSpielerGes := AnzSpieler; Spiel.Owner := Spielername;
i := lenght(arrSpiele); if i < 0 then i := 0; arrSpiele[i-1] := Spiel; Spiel.Free; end;
end; |
Allerdings musst du für dass array auch irgendwo speicher reservieren:
Delphi-Quelltext 1:
| setlength (array, laenge); |
______________________________________________
|
|
morvister 
Hält's aus hier
Beiträge: 15
XP
Delphi 2005 Prof.
|
Verfasst: Di 05.08.08 20:33
Hallo bolder, danke für die antwort!
Ich habe mich nun nach deinem hinweis richten wollen und in die FormCreate-Prozedur den SetLEngth reingepackt:
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| procedure TForStart.FormCreate(Sender: TObject); begin
SetLength(arrSpiele, 100);
end; |
Die EAccessViolation-Exception krieg ich aber immer noch. Ist FormCreate der falsche Ort dafür?
danke und gruß
morvi
|
|
FinnO
      
Beiträge: 1331
Erhaltene Danke: 123
Mac OSX, Arch
TypeScript (Webstorm), Kotlin, Clojure (IDEA), Golang (VSCode)
|
Verfasst: Di 05.08.08 22:12
wenn du die länge eh fest machen willst reicht auch
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| procedure bla(); var arrSpiele: Array[1..100] of String begin end; |
|
|
morvister 
Hält's aus hier
Beiträge: 15
XP
Delphi 2005 Prof.
|
Verfasst: Di 05.08.08 22:31
Hallo, habe die anderen Helfer vorhin glatt überlesen...sorry
Danke euch allen!
Ich bin nun ein kleines Stück weiter. Der SetLength war ein Problem, ein weiteres war aber anscheinend, dass ich, bevor ich die Array-Felder füllen kann, erst mal zu dem jeweils neuen Element (anzSpiele -1) mit TSpiel.Create eine Instanz erzeugen muss...Versteh ich zwar nicht, aber nachdem ich das getan habe, konnte ich zumindst 3 Spiele öffnen...just in diesem Augenblick fällt mir auf, dass mein ganzes Vorhaben blödsinnig ist, weil ich nur 1 ServerSocket-Komponente haben werde, und somit das öffnen von n Spielen keinen Sinn macht.
Nichts desto trotz liegt mir sehr viel daran, das Problem zu erkennen. Was derzeit passiert ist, dass ich 2-3 mal Form2 aufrufen kann und 2 - 3 mal das Array befüllt wird und DANN kommt die EAccessViolation
Ich denke nicht, dass man mir helfen kann, ohne das Projekt zur Verfügung zu haben, deshalb lade ich mal ein .rar mit allen Dateien außer der .exe hoch.
Ich bin mit meinem Latein echt am Ende...Hilfe!
P.S: Wie bereits geschrieben, bin ich OOP-Anfänger und das hier soll auch mein erstes kleines Spielchen werden...also bitte nicht zu doll schimpfen über meinen Code *fleh*
Danke 
Einloggen, um Attachments anzusehen!
|
|
Lossy eX
      
Beiträge: 1048
Erhaltene Danke: 4
|
Verfasst: Do 07.08.08 13:45
Kleine Anmerkung.
Delphi-Quelltext 1: 2: 3:
| Spiel := TSpiel.Create; arrSpiele[i-1] := Spiel; Spiel.Free; |
Das da ist falsch. Das Objekt wird sehr wohl noch benötigt.
Du erzeugst eine Instanz einer Klasse und merkst dir in dem Array lediglich den Pointer der Instanz. Wenn du die Instanz danach wegschmeißt zeigt der Pointer in dem Array noch auf den Speicherbereich an dem sich die Klasse befunden hatte. Allerdings ist dieser Speicherbereich wieder frei verfügbar. Beim 2ten oder 3ten Aufruf wird er scheinbar überschrieben und dann knallt es. Es kann aber jederzeit knallen sobald nur jemand auf den Speicherbereich zugreifen möchte.
Objekte dürfen erst freigegeben werden, wenn sie wirklich nicht mehr benötigt werden.
_________________ Nur die Menschheit ist arrogant genug, um zu glauben sie sei die einzige intelligente Lebensform im All. Wo nicht mal das nachhaltig bewiesen wurde.
|
|
morvister 
Hält's aus hier
Beiträge: 15
XP
Delphi 2005 Prof.
|
Verfasst: Do 07.08.08 16:19
Ich verstehe...das bedeutet wohl, dass ich die Instanzen der Klasse TSpiel direkt im Array erzeugen müsste, wenn ich gleichzeitig mehrere Spiele verwalten will, oder? In der Objektvariable 'Spiel' ist ja nur Platz für 1 Spiel, nicht für n Spiele. Und da ich die Instanz nicht wegschmeißen darf, so wie es im Moment ist, darf ich in der Variablen sicher auch keine neue Instanz erzeugen, da die alte dann genauso weg wäre, richtig?
|
|
Tilman
      
Beiträge: 1405
Erhaltene Danke: 51
Win 7, Android
Turbo Delphi, Eclipse
|
Verfasst: Do 07.08.08 17:00
_________________ Bringe einen Menschen zum grübeln, dann kannst du heimlich seinen Reis essen.
(Koreanisches Sprichwort)
|
|
Lossy eX
      
Beiträge: 1048
Erhaltene Danke: 4
|
Verfasst: Do 07.08.08 20:00
Um das evtl. noch etwas weiter auszuholen. Wenn du eine Klasse anlegst, dann bekommst du einen Zeiger auf die Instanz zurück. Den kannst du beliebig oft kopieren. Dadurch veränderst du aber keine Instanz und erstellst auch keine Kopie davon. Da du bei allem lediglich die Adresse kopiert hast.
Evtl mal ein Beispiel ohne das Array. Mag sein, dass das evtl. verwirrt.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| var Spiel_1, Spiel_2, Spiel_3: TSpiel; begin Spiel_1 := TSpiel; Spiel_2 := Spiel_1; Spiel_3 := Spiel_2; end; |
Bei diesem Code zeigen alle Spiel_X auf die selbe Instanz. Wenn du jetzt eine eninzige davon frei gibst sind alle weg. Es mag sein, dass sie evtl. noch kurzzeitig funktionieren aber der Speicher kann jederzeit mit irgendwas anderem überschrieben werden. Und dann kracht es.
_________________ Nur die Menschheit ist arrogant genug, um zu glauben sie sei die einzige intelligente Lebensform im All. Wo nicht mal das nachhaltig bewiesen wurde.
|
|
morvister 
Hält's aus hier
Beiträge: 15
XP
Delphi 2005 Prof.
|
Verfasst: Do 07.08.08 20:48
Danke für die Erläuterung,ich habe verstanden 
|
|
|