Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Zugriffsverletzung (https://www.delphipraxis.net/115009-zugriffsverletzung.html)

Hybrid666 4. Jun 2008 11:30


Zugriffsverletzung
 
Servus,

ich schreibe grade ein kleines netzwerk spiel und ich bekomme ab und zu einen fehler an einer stelle im code, die sehr oft ausgeführt wird. Der fehler wird manchmal erhoben, wie gesagt, die prozedur wird verdammt oft ausgeführt. wenn aber der fehler einmal geraised war, wird er JEDESMAL wenn die prozedur ausgeführt wird, wieder erhoben.

Hier die prozedur:
Delphi-Quellcode:
function TForm1.CheckWin (WinColor : TColor) : Boolean;
var
   I, J : Integer;
   HasWon : Boolean;
begin
   HasWon := False;
   for I := 1 to 5 do
   begin
      for J := 1 to 4 do
      begin
         try
         if (TPanel (FindComponent ('p' + IntToStr (J) + IntToStr (I))).Color = WinColor) and
            (TPanel (FindComponent ('p' + IntToStr (J) + IntToStr (I + 1))).Color = WinColor) and
            (TPanel (FindComponent ('p' + IntToStr (J) + IntToStr (I + 2))).Color = WinColor) and
            (TPanel (FindComponent ('p' + IntToStr (J) + IntToStr (I + 3))).Color = WinColor) then
               HasWon := True;
         if (TPanel (FindComponent ('p' + IntToStr (J) + IntToStr (I))).Color = WinColor) and
            (TPanel (FindComponent ('p' + IntToStr (J + 1) + IntToStr (I + 1))).Color = WinColor) and
            (TPanel (FindComponent ('p' + IntToStr (J + 2) + IntToStr (I + 2))).Color = WinColor) and
            (TPanel (FindComponent ('p' + IntToStr (J + 3) + IntToStr (I + 3))).Color = WinColor) then
               HasWon := True;
         if (TPanel (FindComponent ('p' + IntToStr (J) + IntToStr (I))).Color = WinColor) and
            (TPanel (FindComponent ('p' + IntToStr (J + 1) + IntToStr (I))).Color = WinColor) and
            (TPanel (FindComponent ('p' + IntToStr (J + 2) + IntToStr (I))).Color = WinColor) and
            (TPanel (FindComponent ('p' + IntToStr (J + 3) + IntToStr (I))).Color = WinColor) then
               HasWon := True;
         finally
         end;
      end;
   end;
   for I := 4 to 8 do
   begin
      for J := 4 to 7 do
      begin
         try
         if (TPanel (FindComponent ('p' + IntToStr (J) + IntToStr (I))).Color = WinColor) and
            (TPanel (FindComponent ('p' + IntToStr (J + 1) + IntToStr (I - 1))).Color = WinColor) and
            (TPanel (FindComponent ('p' + IntToStr (J + 2) + IntToStr (I - 2))).Color = WinColor) and
            (TPanel (FindComponent ('p' + IntToStr (J + 3) + IntToStr (I - 3))).Color = WinColor) then
               HasWon := True;
         finally
         end;
      end;
   end;
   result := HasWon;
end;
Der fehler tritt immer in den FindComponents auf, die panels existieren auch alle, die er prüft.

Der Fehler:
Zitat:

Access violation at Address <ADDRESSE>. Read of Address <ADRESSE>
Warum wird er erhoben? greife ich zu schnell auf findcomponent zu? Habe es mal in try .. finally blocks gesetzt, allerdings raised er den fehler TROTZDEM!

Danke für die Hilfe.

MfG

[edit=SirThornberry] Mfg, SirThornberry[/edit]

Bernhard Geyer 4. Jun 2008 11:36

Re: Unbekannter Fehler
 
Zitat:

Zitat von Hybrid666
Habe es mal in try .. finally blocks gesetzt, allerdings raised er den fehler TROTZDEM!

Dann schau dir mal die Sprachdefinition für try...finally an. Was du willst ist ein try...except-Block.

Ansonsten: Wieso speicherst du dir nicht alle Controls in einem (hier 4*5 großen) Array (array[1..5, 1..4] of TPanel?

Hybrid666 4. Jun 2008 11:47

Re: Unbekannter Fehler
 
Also, mit try except kommt der fehler nicht mehr, allerdings wird die prozedur trotzdem nicht komplett ausgeführt, da er, auch wenn alle gewinnbedingungen erfüllt sind, nicht erkennt das jemand gewonnen hat. wo rührt der fehler her?

dominikkv 4. Jun 2008 12:00

Re: Unbekannter Fehler
 
Dann versuche mal nicht direkt auf TPanel zu casten, sondern den as-Operator zu verwenden... wenn beim Cast ein fehler auftritt kommt dann eine aussagekräftigere Fehlermeldung.

hoika 4. Jun 2008 12:02

Re: Unbekannter Fehler
 
Hallo,

Die Anzahl der Panels ist wohl dynamisch ?
FindComponent kann auch NIL sein.
Ich würde die Panela zumindestens beim Start der Prozedur einmal ermitteln

Delphi-Quellcode:
var
  Panel1_1, Panel1_2... : TPanel;
begin
  Panel1_1_1:= TPanel (FindComponent ('p' + IntToStr (J) + IntToStr (I)));
  Assert(Panel1_1_1<>NIL);

per Assert findest du dann deinen NIL Zugriff.


Heiko

Hybrid666 4. Jun 2008 12:17

Re: Unbekannter Fehler
 
nein, die anzahl ist nich dynamisch, es gibt 8 spalten a 7 zeilen. die panels sind mit x und y koordinate nummeriert, also p11, p12, p13 usw...also kann ich 100%ig sagen das alle panels auf die ich zugreife auch existiert.

tomsel 4. Jun 2008 12:23

Re: Unbekannter Fehler
 
Werden die Panels automatisch angelegt oder hast du das im Designer gemacht? Bei letzterem könntes du dich evtl. mit der Namensgebung vertan haben?

Sharky 4. Jun 2008 12:27

Re: Unbekannter Fehler
 
Hai Hybrid666,

mal unabhängig von dem direkten Problem:

Ich würde nicht über die Farbe der Panels auswerten ob ein "Spiel" gewonnen wurde.
Wenn Du weisst das es eine Matrix 8x7 gibt würde ich einfach ein zweidimensionales Array definieren und dort eintragen welche Felder richtig sind.

Hybrid666 4. Jun 2008 12:29

Re: Unbekannter Fehler
 
Zitat:

Zitat von tomsel
Werden die Panels automatisch angelegt oder hast du das im Designer gemacht? Bei letzterem könntes du dich evtl. mit der Namensgebung vertan haben?

Ich hab sie im designer gemacht und die namen schon 3 mal überprüft.

tomsel 4. Jun 2008 12:36

Re: Unbekannter Fehler
 
OK, OK, War nur so ne Idee...

Dann ermittle doch zunächst mal die genaue Fehlerpostition. Mit zusätzlichem Code, durch teilweises auskommentieren, oder aktiviere die Sprachexceptions in den Debuggeroptionen, oder..., oder... oder...

SirThornberry 4. Jun 2008 12:39

Re: Zugriffsverletzung
 
Zitat:

Access violation at Address <ADDRESSE>. Read of Address <ADRESSE>
Diese Adressen wären sehr sinnvoll zu wissen wenn du Hilfe erwartest.

Wenn ich bedenke das die Methode mehrfach aufgerufen wird ist es hier mehr als nur sinnvoll anstelle von FindComponent ein Array zu verwenden denn wie der Name schon sagt: FINDComponent - es wird also jedesmal gesucht. Ebenso könnte man auch überall ein Sleep rein schreiben um das ganze noch ein wenig auszubremsen.

hoika 4. Jun 2008 12:39

Re: Unbekannter Fehler
 
Hallo

for J := 4 to 7 do

(TPanel (FindComponent ('p' + IntToStr (J + 3)


J=7 ergibt p10

10 als Zeile hast du aber gar nicht, oder ?.


Heiko

Muetze1 4. Jun 2008 12:48

Re: Zugriffsverletzung
 
Wie schon angedeutet ist der jetzige Code der falsche Weg. Du hast hier massive Probleme und man diese deutlich darauf schieben, dass du in deinem Code-Design nicht Datenverarbeitung und Datendarstellung trennst. Deine Oberfläche soll nur die Daten darstellen, aber nicht halten oder als Basis der Verarbeitung dienen. Wäre dies beachtet worden, dann hättest du vllt. noch falsch angezeigte Oberflächenteile, aber immerhin einen richtigen Programmablauf mit dem richtig ermittelten Status (gewonnen, etc).

Also nochmals als eindringlicher Hinweis: Lege dir ein zweidimensionales Array an, wo du die Werte drin hälst und aktualisiere deine Panels entsprechend den Daten aus diesem Array.

Auch ist der Name einer Komponente Schall und Rauch und sollte niemals Einfluß auf den Programmablauf haben, ansonsten wäre es ein sicheres Zeichen, dass die Oberfläche nicht getrennt wäre. Somit: Lege dir als privaten Member ein 2-Dimensionales Array (oder eindimensional, also MOD/DIV nutzen) an in deiner Form, in der du die Panelinstanzen entsprechend hinterlegst. Danach kannst du beim aktualisieren der Oberfläche sogar direkt von Array-Element (Daten) zu Array-Element (Darstellung) arbeiten. Irgendwelche Unsicherheiten mit eventuell nicht gefundenen Panels sind damit schon von vornherein ausgeschlossen.

Wer FindComponent() und das nicht gerade in einem eigenen, allgemeinen GUI Streaming Clienten o.ä., der hat falsch programmiert. Diese Funktion ist langsam und wenn man sie dann noch falsch einsetzt (Rückgabewert überprüfen), dann kommt es zu solchen Fehlerausprägungen. Im Normalfall hat man seine nötigen Instanzen fest hinterlegt und arbeitet mit ihnen, aber sucht sie nicht ständig. Das wäre wie jeden Pinsel während des Zeichnens direkt auswaschen und verwahren um ihn dann alle paar Sekunden erneut aus dem Schrank zu holen zum Zeichnen und danach gleich wieder saubermachen und in den Schrank weglegen. Und wenn du schon selber sagst, dass die Routine ständig/oft aufgerufen wird, dann wäre spätestens dies das KO-Kriterium für FindComponent(), selbst bei Programmen ohne Daten/Oberflächentrennung.

Sharky 4. Jun 2008 12:52

Re: Zugriffsverletzung
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hihi...

ich erlaube mir mal ein einfaches 0815 Beispiel anzuhängen :oops:

Hybrid666 4. Jun 2008 12:57

Re: Unbekannter Fehler
 
Zitat:

Zitat von hoika
Hallo

for J := 4 to 7 do

(TPanel (FindComponent ('p' + IntToStr (J + 3)


J=7 ergibt p10

10 als Zeile hast du aber gar nicht, oder ?.


Heiko

baum wald theorie -.- danke.

und zu dem ich könnte auch sleep einbaun: das issn kleines game, ich bin noch net sooo weit um programmieren und ich hab das game in paar stunden kurz runtergeschrieben und mir net allzuviele gedanken gemacht, also net so streng sein pls :P

tomsel 4. Jun 2008 13:03

Re: Zugriffsverletzung
 
Zitat:

und zu dem ich könnte auch sleep einbaun
Ist das Spiel trotz FindComponent immer noch zu schnell?


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:58 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