Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Debuggen einer Schleife (https://www.delphipraxis.net/178604-debuggen-einer-schleife.html)

MrMooed 16. Jan 2014 21:08

Debuggen einer Schleife
 
Guten Abend DPler,

langsam glaube ich, dass mich Delphi trollen will.
Innerhalb einer Schleife kommt es regelmäßig zu einer AV. Jedoch ist das komische, dass sie immer an einer anderen Stelle auftritt. Mal nach der 10.000 Iteration, mal "erst" nach der 14.000 :pale:

Mit einigen try-except-Blöcken konnte ich nun nachvollziehen, dass es *scheinbar* an dem Constructor eines Objekts liegt.
Delphi-Quellcode:
type
FeldArray1D = Array of TFeld;
var
folgeZustand, Zustand: TStack;
aArray: FeldArray1D
Feld: TFeld;
begin
for y:=0 to High( aArray ) do
      try
        folgeZustand.push( TZustand.create( without(aArray, y), Feld, TZustand( Zustand.top ) ) );
      except
        showmessage('Fehler bei Zustand.create'); // Wird ausgelöst
      end;
end;
Nur das (für mich) Komische ist, dass der try-except-Block in dem constructor nicht ausgelöst wird

Delphi-Quellcode:
constructor TZustand.create(const pBrennt: FeldArray1D; const pGeloescht: TFeld;
  const pVorgaenger: TZustand);
begin
  try
  lVerbrannt := pBrennt;
  fGeloescht := pGeloescht;
  zVorgaenger := pVorgaenger;
  except
    showmessage('Fehler in create'); // Keine Reaktion
  end;
end;
Kann es evtl. sein, dass nur eine begrenzte Anzahl an Objekten erstellt werden kann ? Das ganze wird wie gesagt mehrere Tausend Mal aufgerufen. :shock:
Oder gibt es einen ganz simplen Trick, mit dem ich per debugger an das Problem herangehen kann ? Denn wenn das ganze mal wieder crashed, kommt nur die AV-Meldung und das CPU-Fenster öffnet sich - nicht die gecrashte Quellcodezeile :roll:

Namenloser 16. Jan 2014 21:45

AW: Debuggen einer Schleife
 
Der Fehler liegt offensichtlich nicht im Konstruktor, sondern woanders, deshalb hilft dir auch der Try-Except-Block dort nichts. Vermutlich zerschießt dir irgendwas den Speicher oder es wird auf eine Struktur zugegriffen, die schon freigegeben wurde. Mehr kann man dazu nicht sagen, ohne den kompletten Source-Code zu haben.

Wie viele Objekte man anlegen kann ist nur durch den Arbeitsspeicher begrenzt. Aber wenn der voll ist, dann kommt keine AV, sondern eine andere Exception, deren genauen Namen ich vergessen habe.

Im Zweifelsfall debugge ich solche Fehler, indem ich so lange alles auskommentiere, bis der Fehler nicht mehr auftritt.

jaenicke 16. Jan 2014 22:02

AW: Debuggen einer Schleife
 
Das ist ein typisches Einsatzgebiet für FastMM. Das sagt dir im FullDebugMode evtl. sofort wo das Problem liegt. ;-)

Uwe Raabe 16. Jan 2014 22:02

AW: Debuggen einer Schleife
 
Zitat:

Zitat von Namenloser (Beitrag 1244032)
Wie viele Objekte man anlegen kann ist nur durch den Arbeitsspeicher begrenzt. Aber wenn der voll ist, dann kommt keine AV, sondern eine andere Exception, deren genauen Namen ich vergessen habe.

EOutOfMemory

himitsu 17. Jan 2014 05:23

AW: Debuggen einer Schleife
 
Zitat:

Delphi-Quellcode:
try
  ...
except
  ShowMessage('nichtssagender Text');
end;

Sowas liebe ich immer.
Delphi-Quellcode:
try
  ...
except
  on E: Exception do begin
    E.Message := E.ClassName + ' in Xyz: ' + E.Message; // hier kann man z.B. auch den Index der Schleife erwähnen
    raise; // oder notfalls ShowException(E, nil); und Dergleichen
  end;
end;
Es gibt auch noch Dinge wie EurekaLog und Co., welche beim Suchen der Fehler helfen.

Wenn sich der Fehler absolut nicht finden lässt, dann kann man es auch mal so versuchen.
Delphi-Quellcode:
try
  // mach was
except
  on E: Exception do begin
    ShowException(E, nil); // <<<<<< hier ein Haltepunkt hin
    // mach es nochmal (hoffentlich tritt der Fehler nochmal auf und man kann sich dabei langsam hindurchdebuggen)
  end;
end;

Furtbichler 17. Jan 2014 06:23

AW: Debuggen einer Schleife
 
Delphi-Quellcode:
...
 for y:=0 to High(aArray) do
    folgeZustand.push
      ( 
       TZustand.create
         ( 
          without(aArray, y),
          Feld,
          TZustand(Zustand.top) /// <<---- ist 'Zustand' instantiiert?
         )
      );
  end;
Und wie ich Bandwurmcode hasse ;-) (schlecht lesbar, fehlerbehaftet, buäh), also schreib das mal übersichtlicher und formatiere deinen Code nächstes Mal zumindest ansatzweise, danke.

Delphi-Quellcode:
type
  FeldArray1D = Array of TFeld;

var
  folgeZustand, Zustand, zustandTop: TStack;
  aArray, subArray: FeldArray1D
  Feld: TFeld;

begin
  zustandTop := TZustand(Zustand.top); // Einmal vor der Schleife gemerkt, reicht.
  for y:=0 to High(aArray) do begin
    subArray := Without(aArray,y);
    neuerZustand := TZustand.create(subArray, Feld, zustandTop);
    folgeZustand.push(neuerZustand);
  end;
end;
Vielleicht ist das ja nun besser lesbar. Und wenn Zustand tatsächlich undefiniert ist (vielleicht sollte das ja eigentlich 'folgeZustand.Top' heißen, dann hättest Du auch deinen Fehler.

himitsu 17. Jan 2014 09:46

AW: Debuggen einer Schleife
 
Zitat:

Einmal vor der Schleife gemerkt, reicht
Nur wenn sich der Wert innerhalb der Schleife nicht verändert.
Aber hier weiß ja keiner was Zustand, Zustand.Top oder Without eigentlich machen.

Allerdings ist das zum Debuggen grunstäzlich erstmal genau richtig gedacht.
- So kann man eventuell mitbekommen wo, in der Schlange, es nun genu knallt.
- kann auch jeden Teil auch mit eigenen Try-Excepts testweise umgeben
- und vorallem kann man die Rückgabewerte testweise mal prüfen
- - if Assigned
- - über eine Haltepunkt-Bedingung
- - kann sich im Except den wert der zwischengespeicherten Rückgaben ansehn
- - usw.

Furtbichler 17. Jan 2014 12:52

AW: Debuggen einer Schleife
 
Zitat:

Zitat von himitsu (Beitrag 1244077)
Zitat:

Einmal vor der Schleife gemerkt, reicht
Nur wenn sich der Wert innerhalb der Schleife nicht verändert.
Aber hier weiß ja keiner was Zustand, Zustand.Top oder Without eigentlich machen.

Ja und 'Doch, z.T.': 'Top' liefert den TOS, Zustand ist ein Stack, der lokal definiert, offenbar nicht instantiiert, nicht als Parameter verwendet und somit auch nicht verändert wird.

Falls Codeteile nicht weggelassen wurden.

MrMooed 17. Jan 2014 14:08

AW: Debuggen einer Schleife
 
Erst einmal Danke für die vielen Antworten und Entschuldigung meinerseits für die etwas .. wirre Frage.

Zitat:

Zitat von jaenicke (Beitrag 1244035)
Das ist ein typisches Einsatzgebiet für FastMM. Das sagt dir im FullDebugMode evtl. sofort wo das Problem liegt. ;-)

Ein vorheriger Fehler hatte immer einen Fehler in der FastMM unit ausgelöst, weswegen ich es Test Weise deaktiviert habe - und vergessen es wieder einzubinden. :oops:
Nachdem es dann wieder eingeschaltet war, kam nicht mehr das CPU-Fenster, sondern er sprang in eine Methode - die der constructor aufruft.
Zitat:

Zitat von Furtbichler (Beitrag 1244113)
[..] Falls Codeteile nicht weggelassen wurden.

Naja, Dinge wie die Initialisierung von Variablen habe ich schon weggelassen. :roll: Den ganzen Code wollte ich niemandem zumuten:lol:

Ziel des ganzen war es jedenfalls, aus einem Zustand (etwa die Stellung auf einem Schachbrett) alle möglichen folge-Zustände zu ermitteln - und die daraus folgenden.
Dem constructor
  • wird ein Array übergeben, dass alle "Spielfiguren" enthällt (außer dem, das bewegt wird)
  • das Feld, welches verändert/ bewegt wurde
  • und der vorherige Zustand
Der Fehler lag letztendlich in der Funktion 'without' - hier sollte ein Array zurückgegeben werden, das alle Elemente außer das gewählte enthällt (Das Feld das bewegt wird).
Delphi-Quellcode:
function without(var aFeldArray: FeldArray1D; aPos: Integer): FeldArray1D;
var
  i, b: Integer;
begin
  SetLength( result,
             High( aFeldArray )
            );
  b := 0;
  for i:=0 to High( aFeldArray ) do
  begin
    if not (i = aPos)
      then begin
        result[b] := aFeldArray[i]; // diese Zeile
        Inc( b ); // mit dieser vertauscht
      end;
  end;
end;
Zitat:

Zitat von himitsu (Beitrag 1244051)
Zitat:

Delphi-Quellcode:
try
  ...
except
  ShowMessage('nichtssagender Text');
end;

Sowas liebe ich immer.
[..]

Obwohl mir die Try-Except (so wie ich sie genutzt habe) nicht viel gebracht haben, werde ich wohl demnächst darauf achten sie vernünftig zu nutzen - danke dafür :roll:

Sir Rufo 17. Jan 2014 15:26

AW: Debuggen einer Schleife
 
Nicht obwohl, sondern weil du diese komische Exceptionbehandlung da so reingefriemelt hast, bringt dir das nichts.

Exceptions nur behandeln, wenn ich dafür eine Ausweichmöglichkeit habe.
Einfach nur einen nichtssagenden Text anzeigen ist keine.

Beispiel:

Eine simple Berechnung
Delphi-Quellcode:
function f( const x : Extended ) : Extended;
begin
  Result := 1/x;
end;
Beim Aufruf von
Delphi-Quellcode:
y := f(0);
wird die Exception Delphi-Referenz durchsuchenEDivByZero ausgelöst.
Na und? Wenn der erfolgreiche Ablauf von dem Wert abhängig ist, dann ist hier wohl ein Fehler passiert und der restliche Ablauf ist somit nicht mehr zu gewährleisten.

Stellen wir uns ein anderes Szenario mit der gleichen Funktion vor.
Die Funktion soll grafisch dargestellt werden. Jetzt ticken die Uhren anders
Delphi-Quellcode:
x := -1;
while x <= 1 do
begin
  try
    y := f( x );
    DrawPoint( x, y );
  except
    on E: EDivByZero do
      NoDataFor( x );
  end;
  x := x + 0.1;
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:48 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz