Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Überprüfung auf true und false-->error


DMDADKT - Fr 02.01.09 20:33
Titel: Überprüfung auf true und false-->error
hey leute!
ich hab ein kleines problem und zwar hab ich hier etwas code. lasse ich die abfrage überprüfen ob etwas bestimmtes true ist klappt alles wunderbar. sollte ich aber wagen ihn nach false zu fragen gibt es folgenden error: Erste Gelegenheit für Exception bei $7C81EB33. Exception-Klasse EAccessViolation mit Meldung 'Zugriffsverletzung bei Adresse 0047EF5D in Modul 'GobbletProject1.exe'. Lesen von Adresse FFFFFFFF'. Prozess GobbletProject1.exe (964)

der code:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
procedure TForm1.Feldaufbau;
var
  i,j,k:integer;
  h: boolean;
begin
h:= false ;
  for i := 1 to 4 do
    for j := 1 to 4 do
      begin
        while (SFeld[i,j,k].IsAssigned = false) or (h = true) do
        begin
          dec(k);
          if k = 0 then h:= true;
        end;
        if h = true then
          Spielfeld[i,j].Picture := ImgNix.Picture
        else
          Spielfeld[i,j].Picture := Bildvariable[ord(SFeld[i,j,k].IsColor)+1,k].picture;
      end;
end;


SFeld ist als array folgenermaßen angelegt:

Delphi-Quelltext
1:
SFeld : array[1..4,1..4,1..4of TFeld;                    


so definiert:

Delphi-Quelltext
1:
2:
3:
4:
for i := 1 to 4 do
  for j := 1 to 4 do
    for k := 1 to 4 do
      SFeld[i,j,k] := TFeld.Create;


und in TFEld existiert

Delphi-Quelltext
1:
2:
3:
4:
function TFeld.IsAssigned : boolean;
begin
  Result := FAssigned;
end;



was kann das sein? was kann ich gegen diesen error tun? wäre schön, wenn mit jemand helfen könnte, muss das nämlich für die schule is ferienende machen :/

danke!


Xentar - Fr 02.01.09 20:38

k ist nicht initialisiert
somit steht da am Anfang "irgendwas" drin, und du greifst auf "irgendwas" zu.


DMDADKT - Fr 02.01.09 20:40

autsch.
danke^^ das hatte ich wohl übersehn
leider geht es immernoch nicht :/
aber schonmal ein guter anfang


Hidden - Fr 02.01.09 20:48
Titel: Re: Überprüfung auf true und false-->error
Hi :wave:

E: Mist, zu spät :(

Gut, dann noch ein paar Formsachen:
Du vergleichst bool'sche Ausdrücke explizit mit true, das kann zu Fehlern führen. Ist auch ein bisschen umständlich formuliert:

"Wenn es wahr ist, dass mein Vater Bäcker ist"
-> "Wenn mein Vater Bäcker ist"

Also statt if a = true then lieber  if a then ..
Und statt if a = false then, nimm  if not a then, das hat den selben Effekt und liest sich außerdem weniger holprig ;)

Wenn du jetzt noch h, i, j und k vernünftig benennen könntest, könnte man den Quelltext sogar lesen :shock: :zwinker:

also statt if a then if StringFound, also nur mal als Beispiel: Aus dem variablennamen sollte die Funktion der variable berreits hervorgehen. Das wichtigste an einem Quelltext ist nämlich, dass ihn jeder lesen kann.

user profile iconDMDADKT hat folgendes geschrieben Zum zitierten Posting springen:
leider geht es immernoch nicht :/
Wenn du noch auf einen Tipp hoffst, müsstest du schon sagen, was nicht geht. Dem entnehme ich mal, dass du einen neuen Thread für das neue Problem aufmachen willst?

mfG,


DMDADKT - Fr 02.01.09 20:57
Titel: Re: Überprüfung auf true und false-->error
user profile iconHidden hat folgendes geschrieben Zum zitierten Posting springen:
Hi :wave:
Du vergleichst boolische Ausdrücke explizit mit true, das kann zu Fehlern führen. Ist auch ein bisschen umständlich formuliert:

ich hasb bei meinem letzten lehrer (ja, er war ein trottel auf dem gebiet) so gelernt und benutze es aus gewohnheit noch so. formuliere ich es allerding in "if not" um kommt der selbe fehler

Zitat:

user profile iconDMDADKT hat folgendes geschrieben Zum zitierten Posting springen:
leider geht es immernoch nicht :/
Wenn du noch auf einen Tipp hoffst, müsstest du schon sagen, was nicht geht. Dem entnehme ich mal, dass du einen neuen Thread für das neue Problem aufmachen willst?


das problem ist leider weiterhin das selbe (oder zumindest ist die fehlermeldung weiterhin gleich
stop. ist sie nicht, das fällt mir aber leider soeben erst auf:
Erste Gelegenheit für Exception bei $7C81EB33. Exception-Klasse EAccessViolation mit Meldung 'Zugriffsverletzung bei Adresse 0047EF62 in Modul 'GobbletProject1.exe'. Lesen von Adresse FFFFFFFF'. Prozess GobbletProject1.exe (3952)
lässt sich damit was anfangen?
gehighlighted wird von delphi immernoch die selbe zeile.

danke für die posts!


Hidden - Fr 02.01.09 20:59

Ist das Objekt im Array, auf das du zugreifst, initialisiert?


jaenicke - Fr 02.01.09 21:08

Und wo initialisierst du jetzt k? Wie sieht der Code jetzt aus?


DMDADKT - Fr 02.01.09 21:09

eventuell fehlt mir das wissen, aber ist das nicht hiermit schon erledigt?

Delphi-Quelltext
1:
2:
3:
4:
for i := 1 to 4 do
  for j := 1 to 4 do
    for k := 1 to 4 do
      SFeld[i,j,k] := TFeld.Create;


(falls die inneren werte gemeint sind, auch die werden danach genullt/auf false gesetzt)


edit @ jaenicke:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
procedure TForm1.Feldaufbau;
var
  i,j,k:integer;
  h: boolean;  //hilfe, falls kein stein sitzt
begin
h := false ;
k := 4;
  for i := 1 to 4 do
    for j := 1 to 4 do
      begin
        while (SFeld[i,j,k].IsAssigned = false) or (h = true) do
        begin
          dec(k);
          if k = 0 then h:= true;                  //abbruch
        end;
        if h = true then
          Spielfeld[i,j].Picture := ImgNix.Picture
        else
          Spielfeld[i,j].Picture := Bildvariable[ord(SFeld[i,j,k].IsColor)+1,k].picture;
      end;
end;

dort


jaenicke - Fr 02.01.09 21:26

Deine Logik ist seltsam: Die Schleife wird ausgeführt solange IsAssigned false ergibt oder h True ist. Wenn jetzt k 0 wird, dann wird h True. Und dann läuft die Schleife ja bis in alle Ewigkeit. ;-)
Meinst du nicht eher das?

Delphi-Quelltext
1:
while not SFeld[i,j,k].IsAssigned and not h do                    
Das andere:
Du setzt k nur einmal am Anfang auf 4, wenn dann k einmal 0 war, wird das ja nie wieder zurückgesetzt. Müsste das nicht vor jedem while passieren?

Willst du nicht einfach nur die Anzahl der Felder, die not IsAssigned sind innerhalb jeder inneren Schleife? Dann zähle die doch einfach in einer for-Schleife.


DMDADKT - Fr 02.01.09 21:32

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Deine Logik ist seltsam: Die Schleife wird ausgeführt solange IsAssigned false ergibt oder h True ist. Wenn jetzt k 0 wird, dann wird h True. Und dann läuft die Schleife ja bis in alle Ewigkeit. ;-)
Meinst du nicht eher das?

Delphi-Quelltext
1:
while not SFeld[i,j,k].IsAssigned and not h do                    
Das andere:
Du setzt k nur einmal am Anfang auf 4, wenn dann k einmal 0 war, wird das ja nie wieder zurückgesetzt.

Willst du nicht einfach nur die Anzahl der Felder, die not IsAssigned sind innerhalb jeder inneren Schleife? Dann zähle die doch einfach in einer for-Schleife.

also das mit k an der falschen stelle stimmt schonmal, danke! selbiges gilt dann wohl auch für h.
und mit der schleife hast du auch recht, nochmals danke^^ da hatte ich wohl einen denkfehler.
herausfinden will ich das erste feld, das assigned ist oder obüberhaupt eins assigned ist

leider bleibt das problem bestehen.. und dieses mal hat sich nichtmal die adresse der zugriffsverletzung geändert :/
derzeit:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
procedure TForm1.Feldaufbau;
var
  i,j,k:integer;
  h: boolean;  //hilfe, falls kein stein sitzt
begin
  for i := 1 to 4 do
    for j := 1 to 4 do
      begin
        h := false ;
        k := 4;
        while (SFeld[i,j,k].IsAssigned = false) or (h = false) do
        begin
          dec(k);
          if k = 0 then h:= true;                  //abbruch
        end;
        if h = true then
          Spielfeld[i,j].Picture := ImgNix.Picture
        else
          Spielfeld[i,j].Picture := Bildvariable[ord(SFeld[i,j,k].IsColor)+1,k].picture;
      end;
end;



Edit: mein gott, danke.. ich hatte schon wieder einen denkfehler und dein "and" überlesen. jetzt funktioniert alles (: danke!!


jaenicke - Fr 02.01.09 21:54

Wobei mir gerade noch etwas auffällt:
k = 0 --> h := true, Zugriff beim nächsten Durchlauf auf SFeld[i,j,0].

Deshalb muss das andersherum sein:

Delphi-Quelltext
1:
while not h and not SFeld[i,j,k].IsAssigned do                    
So wird in der Standardeinstellung die zweite Prüfung nicht mehr ausgeführt. Um das sicherzustellen solltest du das vorher explizit setzen:

Delphi-Quelltext
1:
{$B-}                    
Das sorgt dafür, dass keine vollständige boolsche Auswertung stattfindet, so dass IsAssigned nicht mehr aufgerufen wird, wenn h schon true ergeben hat. (weil dann alles zusammen nicht mehr true ergeben kann)

Die andere Sache:
Die Vergleiche wie "= false" und so sind nicht nur schlechter Stil sondern schlicht falsch. Das wurde ja auch bereits geschrieben, dass das Fehler geben kann. Warum wird hier genauer beschrieben:
http://www.delphi-treff.de/tutorials/objectpascal/programmierung-mit-boolean-werten/page/4/


Hidden - Fr 02.01.09 23:15

Hi,

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:

Delphi-Quelltext
1:
while not h and not SFeld[i,j,k].IsAssigned do                    
Und mit ein bisschen Umformungslogik kommt man dann auf while not (h or SFeld[i,j,k].Assigned) do. Nicht, dass das für den Computer einen Unterschied machen würde, was der Compiler draus macht ist sowieso nochmal was anderes. Aber ich finde das noch ein Stückchen besser lesbar :)

@ {$B-}: aber ist denn die Auswertungsreihenfolge damit schon garantiert? Imho kann da immernoch SFeld[i,j,k].IsAssigned zuerst überprüft werden :?:

mfG,


jaenicke - Fr 02.01.09 23:20

Ausgewertet wird immer von links nach rechts :!:

Wenn die vollständige Auswertung boolscher Ausdrücke nicht aktiviert ist (das ist die Standardeinstellung), dann wird abgebrochen sobald das Ergebnis der Auswertung klar ist.
Dies kann mit {$B-} bzw. {$B+} explizit deaktiviert und aktiviert werden, wobei man nach der Aktivierung mit {$B+} es nach dem entsprechenden Quelltext wieder deaktivieren sollte, wie es Standard ist. Denn dies spart ja etwas Rechenzeit.


Hidden - Fr 02.01.09 23:27

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Ausgewertet wird immer von links nach rechts :!:
Oh! :shock:

Sry, ich dachte der Compiler könnte das noch beliebig umformen und das zuerst auswerten, was nach bestimmten Kriterien im Verhältnis zum Auswertungsaufwand am wahrscheinlichsten zum Abbruch führt. Danke, dass wir das richtiggestellt haben :D

mfG,


Oreaden - Fr 02.01.09 23:32

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Ausgewertet wird immer von links nach rechts :!:


Steht jedenfalls in der Hilfe.

Schöne Grüße
OREADEN


DMDADKT - Mo 05.01.09 00:20

Für alle die wissen wollen, bei was sie da eigentlich geholfen haben, hab ich hier mal die ziemlich fertige version hochgeladen. einzig die trefferzone der steine ist evtl noch ein problem, allerdings nicht das dieses threads. viel spaß!


E: uuui, downloads :>