Entwickler-Ecke
Sonstiges (Delphi) - Wo liegt hier der Fehler?
Popov - Mo 07.04.03 15:45
Titel: Wo liegt hier der Fehler?
Ich sehe keinen - aber vielleicht sieht einer von euch es. Anbei ein wenig Code. Mein eigentliches Programm hab ich bis auf diese Zeilen reduziert und leicht modifiziert. Es werden also keine Grafiken geladen, sondern erstellt. Das hat aber auf den Fehler keinen Einfluß.
Wenn man das Programm startet und gleich danach die
Leertaste drückt (
und gedrückt läßt) kommt früher oder später eine Fehlermeldung. Das Programm bricht mit einer EAccessViolation Fehlermeldung ab.
Wie gesagt muß man dazu das Programm starten und die Leertaste gedrückt lassen. Bei mir bricht es in der vierten Zeile mit der Fehlermeldung ab. Es kann aber auch später sein, vor allem dann, wenn man die Taste auch später erst gedrückt hat.
Die einzige Komponente die man für dieses Beispiel braucht ist der Timer:
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:
| implementation
{$R *.DFM}
const MatrixMaxX = 40; MatrixMaxY = 20;
var Matrix: array[0..MatrixMaxX, 0..MatrixMaxY] of Byte; Bmp: TBitmap; BmpA: TBitmap; ax, ay: Integer;
procedure TForm1.FormCreate(Sender: TObject); begin Timer1.Interval := 20; Bmp := TBitmap.Create; Bmp.Width := MatrixMaxX * 16; Bmp.Height := MatrixMaxY * 16;
BmpA := TBitmap.Create; BmpA.Canvas.Brush.Color := clBlack; BmpA.Width := 16; BmpA.Height := 16; end;
procedure TForm1.FormDestroy(Sender: TObject); begin Bmp.Free; BmpA.Free; end;
procedure TForm1.Timer1Timer(Sender: TObject); begin if ay > MatrixMaxX then Exit; if ax > MatrixMaxX then begin ax := -1; ay := ay + 1; end; ax := ax + 1;
Bmp.Canvas.Draw(ax * 16, ay * 16, BmpA); Canvas.Draw(0, 0, Bmp); end;
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char); begin if (Key = ' ') and not (ay > MatrixMaxY) then Matrix[ax, ay + 1] := 0; end; |
Motzi - Mo 07.04.03 16:11
Also soweit ich das sehe initialisierst du die beiden Variablen ax und ay nicht..!
mimi - Mo 07.04.03 16:26
mal ne frage: wo wird in ax und ay geschrieben ? und was soll da drinen stehen ?
Aya - Mo 07.04.03 17:15
Hi,
es kann nur an dieser Zeile hier liegen:
Quelltext
1:
| if (Key = ' ') and not (ay > MatrixMaxY) then Matrix[ax, ay + 1] := 0; |
und da es in dieser Zeile nur an der Matrix hinten liegen kann, würde ich mal tippen das es an dem ay+1 liegt... schreib da mal nur ay hin ;)
Au'revoir,
Aya~
mimi - Mo 07.04.03 17:24
jetzt weiß ich woran es liegt: du schreibst im timer -1 hin nun musst du im onkey ereignis eine abfage machen ob -1 ist.... oder nicht....
und du musst im onkey ereinigs schauen ob ay+1 größer als die höhe ist....
Aya - Mo 07.04.03 17:28
| mimi hat folgendes geschrieben: |
jetzt weiß ich woran es liegt: du schreibst im timer -1 hin nun musst du im onkey ereignis eine abfage machen ob -1 ist.... oder nicht....
und du musst im onkey ereinigs schauen ob ay+1 größer als die höhe ist.... |
Nein, denn direkt nachdem er ax:=-1 macht, erhöht er eswieder um 1, so das es dann 0 ist ;)
Au'revoir,
Aya
Popov - Mo 07.04.03 17:35
@Mozi: ax und ay sind globale Variablen. Siehe also da.
@Mimi: Wo wird in ax und ay geschrieben? Siehe Timerprozedur.
Bitte fragt nicht nach Sinn des Codes. Es ist alles entfernt worden was nicht für die Fehlersuche notwendig ist.
@Aya: Es hat mit +1 nichts zu tun. Auch ohne +1 kommt der Fehler. Allerdings siehts du es richtig. Ohne diese Zeile gibt es keine Fehlermeldung.
@Mimi: Die ganzen Rechnungen haben schon ihren Sinn. Auch so:
Quelltext
1:
| if (Key = ' ') and not (ay > MatrixMaxY) then Matrix[ax, ay] := 0; |
gibt es eine Fehlermeldung.
Aya - Mo 07.04.03 17:38
Hi,
dann mach mal aus dem > ein >= in dieser Zeile:
Quelltext
1: 2:
| if ay > MatrixMaxX then Exit; if ax > MatrixMaxX then begin |
und vorallem mach da mal ein:
MatrixMax
Y hin (oder is das absicht?)
Au'revoir,
Aya~
mimi - Mo 07.04.03 17:41
also ich würde mal an deiner stelle bei on KeyPress ausgeben was in ax und ay steht ich wette da steht irgenwas drin.... was da nicht reinsoll
Popov - Mo 07.04.03 18:20
Ich hab den Fehler.
Den hab ich eigentlich schon nach mimi's -1 Hinweis, hab aber par Minuten gebraucht bis ich es gemerkt habe.
Es ist doch so: Delphi ist eine Multidingsbums Sprache. Das heißt, daß Prozeduren Ereignisorientiert aufgerufen werden. Hier haben wir zwei Prozeduren: einen Timer, der alle X Millisekunden aufgerufen wird. Dann haben wir OnKeyPress, das beim Tastenduck aufgerufen wird. Die Frage ist jetzt ob die Prozeduren warten bis die andere fertig ist, oder die andere Prozedur unterbrechen (bzw. parallel aufgerufen werden). In den zweiten Fall kann es vorkommen, daß ax noch -1, während OnKeyPress aufgerufen wird. In diesem Fall wird ax mit einem -1 angesprochen.
Ich hab den Code jetzt so abgeändert und es funktioniert:
Quelltext
1: 2: 3: 4: 5: 6: 7:
| procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char); begin if (ax < 0) or (ax > MatrixMaxX) then Exit; if (ay < 0) or (ay > MatrixMaxY) then Exit;
if (Key = ' ') and not (ay > MatrixMaxY) then Matrix[ax, ay] := 0; end; |
Also danke für das Brainstorming.
Motzi - Mo 07.04.03 18:32
| Popov hat folgendes geschrieben: |
| Es ist doch so: Delphi ist eine Multidingsbums Sprache. Das heißt, daß Prozeduren Ereignisorientiert aufgerufen werden. Hier haben wir zwei Prozeduren: einen Timer, der alle X Millisekunden aufgerufen wird. Dann haben wir OnKeyPress, das beim Tastenduck aufgerufen wird. Die Frage ist jetzt ob die Prozeduren warten bis die andere fertig ist, oder die andere Prozedur unterbrechen. In den zweiten Fall kann es vorkommen, daß ax noch -1, während OnKeyPress aufgerufen wird. In diesem Fall wird ax mit einem -1 angesprochen. |
Das dürfte aber eigentlich nicht das Problem sein, da die Windows-Messages nacheinander abgerabeitet werden und dein Prog verwendet schließlich keine Threads und ruft auch nirgendwo Application.ProcessMessages auf oder?
Dass ax und ay globale Variablen sind hab ich schon gesehen, aber initialisiert werden sie in dem obigen Code trotzdem nicht.
Aber nachdem jetzt alles funzt hat sich das ja eh erledigt...
mimi - Mo 07.04.03 18:39
doch!
er hat ein Timer der wird immer wieder aufgerufen und wenn er jetzt eine taste drück kann in ax -1 stehen...
Popov - Mo 07.04.03 18:48
| Motzi hat folgendes geschrieben: |
| Dass ax und ay globale Variablen sind hab ich schon gesehen, aber initialisiert werden sie in dem obigen Code trotzdem nicht. |
Jetzt sag mal genau was du mit initialisieren meinst. Oder meinst du hier das zuweisen der ersten Werte? Nunja, wäre ax und ay <> 0, dann hätte ich das auf der Grafik gesehen. ax und ay waren also 0 beim Start.
Zu der Sache mit dem Abarbeiten der Prozeduren. Eigentlich bin ich deiner Meinung, aber warum tritt das Problem jetzt nicht auf?
Motzi - Mo 07.04.03 19:43
| Popov hat folgendes geschrieben: |
Jetzt sag mal genau was du mit initialisieren meinst. Oder meinst du hier das zuweisen der ersten Werte? Nunja, wäre ax und ay <> 0, dann hätte ich das auf der Grafik gesehen. ax und ay waren also 0 beim Start.
Zu der Sache mit dem Abarbeiten der Prozeduren. Eigentlich bin ich deiner Meinung, aber warum tritt das Problem jetzt nicht auf? |
Mit initlialisieren meine ich das Zuweisen der Ausgangswerte. Fehlende Initialisierungen könnten teuflische Fehler verursachen die erst viel später auftreten, weshalb die eigentlich Fehlerursache ziemlich schwer festzustellen ist.
Warum der Code jetzt funktioniert? Ganz einfach, weil du jetzt explizit jeden Fall ausschließt, in dem entweder ax oder ay ein nicht existierendes Array-Feld referenzieren! ;)
mimi - Mo 07.04.03 19:48
und du hast da einen fehler beoben bei if ax > ay then exit;
Motzi - Mo 07.04.03 19:55
Ok.. ich glaube der Fehler ist eine Kombination aus 3 Stellen.. aus dem Original-Code:
1) im OnTimer
Quelltext
1:
| if ay > MatrixMaxX then Exit; // falscher Vergleich |
2)im OnKeyPress
Quelltext
1:
| if (Key = ' ') and not (ay > MatrixMaxY) then Matrix[ax, ay + 1] := 0; // das +1 weg |
3) im OnTimer
Quelltext
1: 2:
| if ay > MatrixMaxX then if ax > MatrixMaxX then |
In beiden Fällen muss der Vergleich auf >= lauten. Denn wenn ax = MatrixMaxX ist wird es nicht auf -1 zurückgesetzt, aber trotzdem nochmal um 1 erhöht.
Popov - Mo 07.04.03 21:36
Ok, das Problem ist weg. Deshalb ist die Lösung sekundär. Aber mal par Worte zu den Punkten:
Quelltext
1:
| if ay > MatrixMaxX then Exit; // falscher Vergleich |
Ist zwar ein Fehler, aber hat mit dem eigentlichen Problem nichts zu tun, da der Fehler auftrit bevor ay > MatrixMaxY ist. Der Fehler kommt davon, daß es vorher nur ein MatrixMax gab und keine MatrixMaxX / ...Y. Das hat aber mit dem eigentlichen Problem nichts zu tun.
Quelltext
1:
| if (Key = ' ') and not (ay > MatrixMaxY) then Matrix[ax, ay + 1] := 0; // das +1 weg |
Das +1 ist schon richtig, da hier die Matrixzeile drunter angesprochen wird. Aber auch ohne das +1 gabs den Fehler.
Quelltext
1:
| if ax > MatrixMaxX then |
Das ist auf jeden Fall ein schlimmer Fehler. Das könnte auch der gesuchte Fehler sein. Werde es noch prüfen.
Motzi - Mo 07.04.03 21:47
| Popov hat folgendes geschrieben: |
Quelltext 1:
| if (Key = ' ') and not (ay > MatrixMaxY) then Matrix[ax, ay + 1] := 0; // das +1 weg |
Das +1 ist schon richtig, da hier die Matrixzeile drunter angesprochen wird. Aber auch ohne das +1 gabs den Fehler. |
Das mag schon sein, nur schließt der Vergleich ay > MatrixMaxY den Fall ay = MatrixMaxY nicht aus wodurch dann mit ay + 1 der Index auserhalb der Matrix liegt! Lösung wäre entweder das +1 zu entfernen oder auch hier den Vergleich auf >= umzuändern..
Aber egal.. nachdem der Fehler ja behoben ist braucht man den Code nicht noch weiter zu zerlegen...
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!