Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Stack-Overflow abfangen (https://www.delphipraxis.net/162259-stack-overflow-abfangen.html)

Sinthuor 14. Aug 2011 22:07

Delphi-Version: 7

Stack-Overflow abfangen
 
Habe ein Programm das die Länge eines vorhandenen Weges von einem Starpunkt zu einem Zielpunkt berechnen soll:
X0000
00000
00000
00000
0000
X
Das klappt, solange in dem Weg keine "Kreise" auftreten (Abzweigungen sind kein Problem):
XXX00
X00X0
X0XXX
X0X0X
XXX0X
etwa liefert als Länge 12;
Problematisch wird es sobald ein Weg vor dem Ziel einen "Kreis bildet":
XXXXX
X
000X
XXXXX
X
0000
XXXXX
Hier kommt es zu einer Endlosschleife und dadurch zu einem Stackoverflow - den ich abfangen und stattdessen eine Fehlermeldung ausgeben möchte.

Mein Code:
Delphi-Quellcode:
class function TFelder.RestWeg(Sender: TObject; last: integer): integer;
var counter,a,b,c,d: integer;
begin
  counter:=0;
      if (TFelder(Sender).Fxpos=5) and (TFelder(Sender).Fypos=5) then counter:=0 //Ziel
else if (felder[TFelder(Sender).Fxpos, TFelder(Sender).Fypos-1].Ftyp<>'Weg') then counter:=11 //Falls keine Verbingung von Start zu Ziel vorhanden
else
  begin
    a:=10; b:=10; c:=10; d:=10;

    if (TFelder(Sender).Fypos>1) and (last<>2) then //last gibt die "Richtung" an, von der gezählt wird
                                                    //-> somit keine Umkehr möglich, wass abermals zu einer Endlosschleife führen würde
    a:=Restweg(felder[TFelder(Sender).Fxpos, TFelder(Sender).Fypos-1], 4)+1;
   
    if (TFelder(Sender).Fypos<5) and (last<>4) then
    b:=Restweg(felder[TFelder(Sender).Fxpos, TFelder(Sender).Fypos]+1, 2)+1;

    if (TFelder(Sender).Fxpos>1) and (last<>1) then
    c:=Restweg(felder[TFelder(Sender).Fxpos-1, TFelder(Sender).Fypos], 3)+1;

    if (TFelder(Sender).Fxpos<5) and (last<>3) then
    d:=Restweg(felder[TFelder(Sender).Fxpos+1,  TFelder(Sender).Fypos], 1)+1;

    counter:=min(a,b);
    counter:=min(counter,c);
    counter:=min(counter,d);
  end;

  result:=counter;
end;
Aufgerufen wird das ganze durch einen Buttonclick:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
CreepLife.text:=inttostr(Tfelder.RestWeg(felder[0,0],0));
Würde den Fehler gerne einfach mit Try ... Except ... End abfangen, und eine Fehlermeldung "Unerlaubter Weg" ausgeben - bin daran jedoch gescheitert.

Luckie 14. Aug 2011 22:29

AW: Stack-Overflow abfangen
 
Lass es laufen und guck, was für eine Exception dir Delphi wirft und genau die fängst du dann in einem try-except-Block ab.

himitsu 14. Aug 2011 22:36

AW: Stack-Overflow abfangen
 
Oder merk dir, wo du schon überall warst und laß es garnicht erst so weit kommen. :angle2:

Sinthuor 14. Aug 2011 22:47

AW: Stack-Overflow abfangen
 
Zitat:

Zitat von Luckie (Beitrag 1116857)
Lass es laufen und guck, was für eine Exception dir Delphi wirft und genau die fängst du dann in einem try-except-Block ab.

Ist eine Exception der Klasse EStackOverflow.
Habe auch schon versucht diese mit try...except aufzufangen (bzw. auch generell jede), das hat aber nicht funktioniert.
Kann mir jemand sagen, wo genau das try bzw. das except in den code gehört?

DeddyH 14. Aug 2011 22:57

AW: Stack-Overflow abfangen
 
Du hast eine Rekursion programmiert. Diese definiert sich eben dadurch, dass eine Routine sich selbst aufruft. Nun darfst Du selbst überlegen, wo ein try-except-Block überall Sinn macht, oder Du beachtest himitsus Hinweis und versuchst eine Endlos-Rekursion (wirklich endlos ist sie ja nicht, wie Du gerade schmerzvoll erfährst) im Vorfeld zu vermeiden, was die sauberere Lösung wäre.

brechi 14. Aug 2011 23:40

AW: Stack-Overflow abfangen
 
uebergib in jeder rekursion die rekusrionstiefe mit, und brich frühzeitig ab (z.b. tiefe 30)

Sinthuor 15. Aug 2011 01:20

AW: Stack-Overflow abfangen
 
Zitat:

Zitat von brechi (Beitrag 1116870)
uebergib in jeder rekursion die rekusrionstiefe mit, und brich frühzeitig ab (z.b. tiefe 30)

Das war eine super Lösung für mich. Vielen Dank! :-D

FredlFesl 15. Aug 2011 06:00

AW: Stack-Overflow abfangen
 
Zitat:

Zitat von Sinthuor (Beitrag 1116876)
Zitat:

Zitat von brechi (Beitrag 1116870)
uebergib in jeder rekursion die rekusrionstiefe mit, und brich frühzeitig ab (z.b. tiefe 30)

Das war eine super Lösung für mich. Vielen Dank! :-D

Das ist keine Lösung, sondern ein Workaround. Denn wenn ein Weg mal länger als 30 Einheiten sein sollte, findest du ihn mit dieser Methode nicht mehr.

jaenicke 15. Aug 2011 06:16

AW: Stack-Overflow abfangen
 
Mal abgesehen davon, dass es extrem viel länger dauert, wenn man sich nicht merkt wo man schon war...

himitsu 15. Aug 2011 06:47

AW: Stack-Overflow abfangen
 
Bedenkt aber, daß man auch etwas mehr Speicher benötigt, wenn man sich den Weg merkt, da dieses für jede Rekusrionsebene einzeln gepeichert (kopiert und erweitert) werden muß.
Also vorallem, wenn man es mit auf den Stack legen würde.


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