![]() |
Zugriffsverletzung nach Modulus
Hi,
sitze schon seit einer Weile an folgendem Problem: In einem Spiel soll ein Spieler durch Karten bewegt werden. Dazu habe ich eine Funktion zur Auswertung der Karten geschrieben. Doch nach einer Konstanten Zahl an Testläufen kommt es immer zu folgendem Problem: Zitat:
Zitat:
Ich hab soweit Code auskommentiert und konnte herausfinden, das ohne folgende Zeilen das Problem nicht mehr auftritt:
Delphi-Quellcode:
player.angle := (player.angle - 1 + 4) mod 4;
Delphi-Quellcode:
player.angle := (player.angle + 1 + 4) mod 4;
Delphi-Quellcode:
player.angle sollte immer in dem Bereich zwischen 0 und 3 gehalten werden und wird auch nur so geändert. Außerdem sollte das keine Zugriffsverletzung auslösen... :?
player.angle := (player.angle + 2 + 4) mod 4;
Weiß jemand, woher soetwas stammen könnte? Schonmal Danke im Vorraus RebellX P.S.: Ich benutze statische und dynamische Arrays, doch auch wenn ich auf die nicht mehr zugreife tritt das Problem auf. P.P.S.: Ich benutze Delphi 7 |
Re: Zugriffsverletzung nach Modulus
Mal ne doofe Idee: kann es sein das du Player irgendwo freigegeben hast (ist das ein Objekt oder ein Record?) :glaskugel:
Ich glaube um ein bisschen mehr Code-Preisgabe wirst du hierbei nicht herumkommen. |
Re: Zugriffsverletzung nach Modulus
Zitat:
A: player ist in der procedure mit var übergeben worden, sonst aber ein array [1..8] of tplayer (record) B: Ich davor und danach darauf zugreifen kann, wenn ich die o.g. Zeilen auskommentiere C: Ich recht wenig freigebe, da das meiste statisch ist und ich mich so nicht drum kümmern muss Das ganze Projekt ist eine Art Brettspiel. Bis zu 8 Spieler können durch 5 Aktionen pro Zug über ein Spielfeld sich bewegen und müssen Punkte erreichen. Dabei werden sie zusätzlich von den verschiedenen Feldern des Spielfeldes bewegt. Heißt also in der Berechnung hat jeder Spieler eine X und Y Koordinate sowie eine Orientierung (halt die Eigenschaft angle, also 0, 90, 180, 270° als 0-3 dargestellt). Zur Anzeige der Bewegung wird dafür wieder rückwärts eine "Animation" erstellt, sprich es wird gespeichert, wie der Spieler bewegt wurde und er wird fürs Anzeigen zurückbewegt. Diese "Animation" wird dann immer weiter verringert, bis der Spieler da angezeigt wird, wo er tatsächlich steht. Das funktionioniert auch ohne die drei Zeilen ohne Probs. Nur sind die unumgänglich um die Spieler zu drehen (oder wie könnte man das einfacher machen?) Ein paar Definitionen von TPlayer etc. :
Delphi-Quellcode:
Die Methode mit der Berechnung:
type
TPlayer = record X, Y, angle: byte; //Animation ani_x, ani_y, ani_z, ani_angle, ani_wait: array of smallint; ani_count: byte; //... unwichtige booleanwerte für Handkarten etc, noch nicht implementiert... end; const Move_1 = $01; Move_2 = $02; Move_3 = $03; Turn_Left = $04; Turn_Right = $05; U_Turn = $06; Back_Up = $07;
Delphi-Quellcode:
Moveplayer und addanimate arbeiten ohne Probleme und auch das Auskommentiere schafft keine Besserung.
procedure execute(befehl: byte; var Aplayer: tplayer);
var i: byte; begin if (befehl = 0) or (befehl > 7) then exit; if befehl <= move_3 then for i := 1 to befehl do begin moveplayer(aplayer, aplayer.angle); end else if befehl = Turn_left then begin aplayer.angle := (aplayer.angle - 1 + 4) mod 4; addanimate(aplayer, AT_Angle, +30); end else if befehl = Turn_Right then begin aplayer.angle := (aplayer.angle + 1 + 4) mod 4; addanimate(aplayer, AT_Angle, -30); end else if befehl = U_Turn then begin aplayer.angle := (aplayer.angle + 2 + 4) mod 4; if random(2) = 1 then addanimate(aplayer, AT_Angle, -60) else addanimate(aplayer, AT_Angle, +60); end else if befehl = Back_Up then begin moveplayer(aplayer, (aplayer.angle + 2 + 4) mod 4); end; end; P.S.: Player heißt da Aplayer, da Player im Hauptprogramm eben ein Array ist |
Re: Zugriffsverletzung nach Modulus
Benutze einfach mal eine Hilfsvariable und teile
Delphi-Quellcode:
in mehrere Anweisungen auf. Auf die Art sieht man z.B. Bereichsunter- oder überschreitungen (etwa durch die Reihenfolge, in der die Summierung ausgewertet wird) viel eher. Player.Angle ist ja BYTE ... also besser erst +4 und dann -1.... nur so eine (ungetestete) Idee ...
player.angle := (player.angle - 1 + 4) mod 4;
|
Re: Zugriffsverletzung nach Modulus
Der Teil aus dem CPU-Fenster passt absolut nicht mit deiner Code-Zeile zusammen.
Kannst du mal in den Optionen die Bereichüberprüfung anschalten. |
Re: Zugriffsverletzung nach Modulus
Bereichsprüfung ist eigentlich schon angeschaltet gewesen, sofern ich mich nicht irre.
zumindest habe ich in jeder Unit {+R} gesetzt gehabt, wobei player.angle nur in case Structuren verglichen wird... Ob es -1+4 ist oder +1+4 macht keinen Unterschied, auch wenn ich -1+4 rausnehme tritt der Fehler auf. |
Re: Zugriffsverletzung nach Modulus
Eine Rechenoperation kann keine Zugriffsverletzung auslösen, also ist es egal ob +1, -1 oder sonstwas.
Es kann höchstens eine Zugriffsverletzung beim Zugriff auf Player erfolgen.
Code:
Wenn aber Player "ungültig" ist, dann gäbe es mit hoher Wahrscheinlichkeit schon beim Lesen einen Fehler und nicht erst bei Schreiben, zumindestens im angegebenen Speicherbereich von $00000000 bis $0000FFFF ( $00030fc0 ).
player.angle := player.angle;
^ ^ ^ Zugriffverletzung "Lesen von Adresse" Zugriffverletzung "[b]Schreiben von Adresse[/b]" |
Re: Zugriffsverletzung nach Modulus
TPlayer ist aber, laut seiner Aussage, ein Record.
|
Re: Zugriffsverletzung nach Modulus
Zitat:
es sei denn dieses Player ist ein Var/Const-Parameter einer Prozedur und der übergebene Parameter-Wert ist "ungültig". Aber wenn sonst alles "korrekt" ist, dann kann der Fehler also nicht in dieser Codezeile stecken. Da er ja angeblich auch Arrays verwendest: Hast du denn schonmal die Bereichprüfung aktivert? (z.B. in den Projektoptionen) |
Re: Zugriffsverletzung nach Modulus
So, hab nochmal sichergestellt, das die Bereichsprüfung an ist (ich kann Integeroverflow etc. erzeugen und krieg nen Fehler).
Hab auch versucht, auf das Modulus zu verzichten und die Animationen (hat zwar dynamische Arrays, hatte aber funktioniert) noch mal rausgenommen. Die Stelle mit ehemals - 1 + 4 sähe nun so aus:
Delphi-Quellcode:
wenn ich davon die 2. Zeile auskommentiere, funzt es ohne Probleme. Wenn ich aber +3 rechne (muss als byte ja gehen, die 1. und 3. Anweisungen stellen sicher, das man im Rahmen von 0..3 bleibt), sagt er wieder Zugriffsverletzung und zeigt im CPU-Fenster auf push $00000400 oder push ebx. Die anderern beiden Fälle hab ich dabei mal auskommentieren können.
while aplayer.angle > 3 do aplayer.angle := aplayer.angle - 4;
aplayer.angle := aplayer.angle + 3; while aplayer.angle > 3 do aplayer.angle := aplayer.angle - 4; Habe noch
Delphi-Quellcode:
am Anfang eingefügt, bringt auch keine Besserung...
if not assigned(@aplayer) then exit;
Und eine Int64 Variable zum Feststellen, ob es mein Speicher ist, auf den ich zugreife hat auch nichts gebracht:
Delphi-Quellcode:
Testint und test sind Int64, test eine sehr große Konstante.
if not aplayer.Testint = test then exit;
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:14 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz