Entwickler-Ecke

Sonstiges (Delphi) - Debugger-Exception-Problem


Angry - Di 13.11.07 17:20
Titel: Debugger-Exception-Problem
Hallo,
habe ein kleines Programm(zu Übungszwecken) geschrieben, welches Kästen in einem 3x3 Feld je nach Klick schwarz oder weiß färben soll.

Hier erstmal der Quelltext:


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:
//Färbt die Kästen je nach Eintrag im Array. lo steht dabei z.B. für LinksOben
procedure check;
begin
if (feld[1,1]=0then (form1.lo.Color:=clwhite) else (form1.lo.Color:=clblack);
if (feld[1,2]=0then (form1.mo.Color:=clwhite) else (form1.mo.Color:=clblack);
if (feld[1,3]=0then (form1.ro.Color:=clwhite) else (form1.ro.Color:=clblack);
if (feld[2,1]=0then (form1.lm.Color:=clwhite) else (form1.lm.Color:=clblack);
if (feld[2,2]=0then (form1.mm.Color:=clwhite) else (form1.mm.Color:=clblack);
if (feld[2,3]=0then (form1.rm.Color:=clwhite) else (form1.rm.Color:=clblack);
if (feld[3,1]=0then (form1.lu.Color:=clwhite) else (form1.lu.Color:=clblack);
if (feld[3,2]=0then (form1.mu.Color:=clwhite) else (form1.mu.Color:=clblack);
if (feld[3,3]=0then (form1.ru.Color:=clwhite) else (form1.ru.Color:=clblack);
end;

//Verändert das Array, also das angeklickte Kästen und die Anliegenden
procedure klick (i,j : integer);
begin
if (feld[i,j]=0then feld[i,j]:=1 else feld[i,j]:=0;
if (i>1and (feld[i-1,j]=0then feld[i-1,j]:=1 else feld[i-1,j]:=0;
if (i<3and (feld[i+1,j]=0then feld[i+1,j]:=1 else feld[i+1,j]:=0;
if (j>1and (feld[i,j-1]=0then feld[i,j-1]:=1 else feld[i,j-1]:=0;
if (j<3and (feld[i,j+1]=0then feld[i,j+1]:=1 else feld[i,j+1]:=0;
end;



Mein Problem:

Der Debugger gibt kein Problem aus und wenn ich auf die Kästchen, außer links oben und rechts oben klicke geht auch alles super!
Wenn ich eines der beiden Kästchen links oder rechts oben anklicke, also im Array feld[1,1] und feld[1,3] kommt folgende Fehlermeldung.

Zitat:
Benachrichtigung über Debugger-Exception

Im Projekt 3x3.exe ist eine Exception der Klasse EAccessViolation aufgetreten. Meldung: Zugriffsverletzung bei Adresse 0044EFBF in Modul '3x3.exe' Lesen von Adresse 000002F8.Prozess wurde angehalten.
Fortsetzen mit Einzelne Anweisung oder Start.


Die angebotene Delphi-Hilfe hat mich auch nicht weitergebracht. Ich hoffe hier kann mir jemand helfen!

Mit freundlichen Grüßen
Angry

Moderiert von user profile iconNarses: Quote- durch Delphi-Tags ersetzt


Narses - Di 13.11.07 18:57

Moin und :welcome: im Forum!

Leider ist der vorgestellte Code zu knapp, um da was zu erkennen. :nixweiss: Zeig doch mal das ganze Programm! ;)

cu
Narses


Sinspin - Di 13.11.07 18:57

Hallo und :welcome: ,

zeig mal die Deklaration deines Feldes und die Procedure die Klick(i,j) aufruft.


Angry - Di 13.11.07 22:05

Okay dann hier die komplette Unit:


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:
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:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    lo: TPanel;
    mu: TPanel;
    mo: TPanel;
    ro: TPanel;
    rm: TPanel;
    ru: TPanel;
    mm: TPanel;
    lm: TPanel;
    lu: TPanel;
    Label1: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure loClick(Sender: TObject);
    procedure moClick(Sender: TObject);
    procedure lmClick(Sender: TObject);
    procedure mmClick(Sender: TObject);
    procedure roClick(Sender: TObject);
    procedure rmClick(Sender: TObject);
    procedure ruClick(Sender: TObject);
    procedure muClick(Sender: TObject);
    procedure luClick(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  feld : array[1..3of array[1..3of integer;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
VAR i,j : integer;
begin
for i:=1 to 3 do begin
for j:=1 to 3 do
feld[i,j]:=0;
end;
end;

procedure check;
begin
if (feld[1,1]=0then (form1.lo.Color:=clwhite) else (form1.lo.Color:=clblack);
if (feld[1,2]=0then (form1.mo.Color:=clwhite) else (form1.mo.Color:=clblack);
if (feld[1,3]=0then (form1.ro.Color:=clwhite) else (form1.ro.Color:=clblack);
if (feld[2,1]=0then (form1.lm.Color:=clwhite) else (form1.lm.Color:=clblack);
if (feld[2,2]=0then (form1.mm.Color:=clwhite) else (form1.mm.Color:=clblack);
if (feld[2,3]=0then (form1.rm.Color:=clwhite) else (form1.rm.Color:=clblack);
if (feld[3,1]=0then (form1.lu.Color:=clwhite) else (form1.lu.Color:=clblack);
if (feld[3,2]=0then (form1.mu.Color:=clwhite) else (form1.mu.Color:=clblack);
if (feld[3,3]=0then (form1.ru.Color:=clwhite) else (form1.ru.Color:=clblack);
end;

procedure klick (i,j : integer);
begin
if (feld[i,j]=0then feld[i,j]:=1 else feld[i,j]:=0;
if (i>1and (feld[i-1,j]=0then feld[i-1,j]:=1 else feld[i-1,j]:=0;
if (i<3and (feld[i+1,j]=0then feld[i+1,j]:=1 else feld[i+1,j]:=0;
if (j>1and (feld[i,j-1]=0then feld[i,j-1]:=1 else feld[i,j-1]:=0;
if (j<3and (feld[i,j+1]=0then feld[i,j+1]:=1 else feld[i,j+1]:=0;
end;

procedure TForm1.loClick(Sender: TObject);
begin
klick (1,1);
check;
end;

procedure TForm1.moClick(Sender: TObject);
begin
klick (1,2);
check;
end;

procedure TForm1.lmClick(Sender: TObject);
begin
klick (2,1);
check;
end;

procedure TForm1.mmClick(Sender: TObject);
begin
klick (2,2);
check;
end;

procedure TForm1.roClick(Sender: TObject);
begin
klick (1,3);
check;
end;

procedure TForm1.rmClick(Sender: TObject);
begin
klick (2,3);
check;
end;

procedure TForm1.ruClick(Sender: TObject);
begin
klick (3,3);
check;
end;

procedure TForm1.muClick(Sender: TObject);
begin
klick (3,2);
check;
end;

procedure TForm1.luClick(Sender: TObject);
begin
klick (3,1);
check;
end;

end.


Narses - Di 13.11.07 23:44
Titel: Re: Debugger-Exception-Problem
Moin!

user profile iconAngry hat folgendes geschrieben:
Wenn ich eines der beiden Kästchen links oder rechts oben anklicke, also im Array feld[1,1] und feld[1,3] kommt folgende Fehlermeldung.
Ich muss gestehen, ich kann nicht erklären, warum diese Exception auftritt (IMHO sollte das nicht passieren :nixweiss:), aber wenn du die Prozedur checkzu einer Methode der Formularklasse machst, dann kommt zumindest keine Exception mehr... :gruebel:

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:
type
  TForm1 = class(TForm)  
    lo: TPanel;
    //...
    procedure luClick(Sender: TObject);
    procedure check;
  private
    //...

var
  Form1: TForm1;
  feld : array[1..3,1..3of integer;

implementation

procedure TForm1.FormCreate(Sender: TObject);
//...

procedure TForm1.check;
begin
  if (feld[1,1]=0then lo.Color:=clwhite else lo.Color:=clblack;
  if (feld[1,2]=0then mo.Color:=clwhite else mo.Color:=clblack;
  if (feld[1,3]=0then ro.Color:=clwhite else ro.Color:=clblack;
  if (feld[2,1]=0then lm.Color:=clwhite else lm.Color:=clblack;
  if (feld[2,2]=0then mm.Color:=clwhite else mm.Color:=clblack;
  if (feld[2,3]=0then rm.Color:=clwhite else rm.Color:=clblack;
  if (feld[3,1]=0then lu.Color:=clwhite else lu.Color:=clblack;
  if (feld[3,2]=0then mu.Color:=clwhite else mu.Color:=clblack;
  if (feld[3,3]=0then ru.Color:=clwhite else ru.Color:=clblack;
end;

Allerdings ist dein Code noch nicht sehr effizient, daran solltest du noch arbeiten. ;)

cu
Narses


jaenicke - Mi 14.11.07 10:05

Das ist relativ einfach ;-).

user profile iconAngry hat folgendes geschrieben:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
//Verändert das Array, also das angeklickte Kästen und die Anliegenden
procedure klick (i,j : integer);
begin
if (feld[i,j]=0then feld[i,j]:=1 else feld[i,j]:=0;
if (i>1and (feld[i-1,j]=0then feld[i-1,j]:=1 else feld[i-1,j]:=0;
if (i<3and (feld[i+1,j]=0then feld[i+1,j]:=1 else feld[i+1,j]:=0;
if (j>1and (feld[i,j-1]=0then feld[i,j-1]:=1 else feld[i,j-1]:=0;
if (j<3and (feld[i,j+1]=0then feld[i,j+1]:=1 else feld[i,j+1]:=0;
end;
Wenn j größer als Eins ist und das Feld Null ist, dann wird 1 zugewiesen. Das ist ja auch ok.
Wenn aber j NICHT größer als Eins ist (else), dann wird dem Feld 0 zugewiesen. Leider gibts das Feld [i, 0] aber gar nicht.

Da bei statischen Arrays AFAIK keine Indexprüfung zur Laufzeit stattfindet, merkt Delphi das nicht. Und an dieser Stelle wird dann an eine Stelle im Speicher geschrieben, wo lieber nix geschrieben werden sollte, mit dem Ergebnis, dass Form1 nil ist. Und da Form1 jetzt nil ist, gibts natürlich Fehler beim Zugriff auf Elemente darin.

Lösung: Das "and" durch ein "then if" ersetzen, dann gilt das else nur für das innere if.


Narses - Mi 14.11.07 10:35

Moin!

user profile iconjaenicke hat folgendes geschrieben:
Das ist relativ einfach ;-).
...allerdings! :autsch: (ich hätte diesen Teil des Codes als nächstes "renoviert", deshalb hab ich mir das gar nicht genauer angesehen... :roll:)

cu
Narses


Angry - Mi 14.11.07 22:08

:oops: da hätt ich auch selber drauf komm könn..

naja fang ja grad erst an...


Logikmensch - Do 15.11.07 06:55

Ja, da bist Du dem "Hanging else problem" aufgesessen. Oben mein Vorschlag zur Vermeidung unnötiger Abfragen (und selbst das ließe sich noch erheblich optimieren).


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
procedure klick (i,j : integer);  
begin  
  feld[i,j] := 1-feld[i,j];  
  if i>1 then feld[i-1,j] := 1-feld[i-1,j];
  if i<3 then feld[i+1,j] := 1-feld[i+1,j];  
  if j>1 then feld[i,j-1] := 1-feld[i,j-1];  
  if j<3 then feld[i,j+1] := 1-feld[i,j+1];  
end;