Autor Beitrag
Visum
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 106



BeitragVerfasst: Mo 16.09.02 21:32 
Hi,
ich hab eine rekursive Prozedur, wobei allerdings ein Stack overflow eintritt (die Rekursion wird korrekt begonnen und beendet, ist aber zu umfangreich).

Wenn ich den Stack overflow-Fehler wegklicke und weitermache, als wäre nichts gewesen, funktioniert das Programm weiter und liefert auch richtige Ergebnisse. Irgendwann aber stürzt das Programm dann komplett ab.

Frage(n):
- Kann ich den Stack overflow irgendwie verhindern?
- Wenn nein, (wie) kann ich die Fehlermeldung verhindern, sodass er direkt einfach weiterrechnet?
- Warum stürzt das Programm am Ende ganz ab?
- Kann ich das irgendwie verhindern?

Ups, ganz schön viele Fragen ...

Visum
Renegade
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 358

Win XP Pro, Win 7 Beta
BDS 2006
BeitragVerfasst: Mo 16.09.02 22:51 
Visum hat folgendes geschrieben:
Ups, ganz schön viele Fragen ...


Stimmt! Und ein bischen Code wäre dazu nicht schlecht!

Gruß Renegade

_________________
Sokrates (468 v.Chr. - 399 v.Chr.)
"Es ist keine Schande, nichts zu wissen, wohl aber, nichts lernen zu wollen."
Tino
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Veteran
Beiträge: 9839
Erhaltene Danke: 45

Windows 8.1
Delphi XE4
BeitragVerfasst: Di 17.09.02 09:02 
Visum hat folgendes geschrieben:
ich hab eine rekursive Prozedur, wobei allerdings ein Stack overflow eintritt (die Rekursion wird korrekt begonnen und beendet, ist aber zu umfangreich).

Was heißt denn zu umfangreich. Ich denke das das Verlassen der Methoden nicht korrekt funktioniert.

Aber wie Renegade schon gesagt hat wäre ein bisschen Code nicht schlecht!

Gruß
TINO
Visum Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 106



BeitragVerfasst: Di 17.09.02 15:08 
Hi,

hier erstmal etwas code:
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
procedure rekursion(x,y,n:integer; pFeld:TFeld);
begin
if not fertig then begin
 if pFeld[x,y]=0 then
  begin
   pFeld[x,y]:=n;
   if pFeld[x,y-1]=0 then rekursion(x,y-1,n+1,pFeld);
   if x mod 2 = 0 then 
    begin 
     if pFeld[x-1,y+1]=0 then rekursion(x-1,y+1,n+1,pFeld);
     if pFeld[x+1,y+1]=0 then rekursion(x+1,y+1,n+1,pFeld);
    end;
  end;
 if n=Anzahl then
  begin
   Ausgabe(pFeld,n);
   fertig:=true;
  end;
end;
end;

TFeld ist ein zweidimensionales Array of Integer, beginnend jeweils bei 1.
fertig ist boolean und anfangs auf False gesetzt.
Anzahl wird auch am Anfang gesetzt, ist auch der Eingabe entsprechend Richtig.

Auf "zu umfangreich" komme ich, da ich Ergebnisse bekomme, solange die Anzahl klein ist (je nach Anordnung bis etwa 5). Alles darüber verursacht, wenn ich es alles auf einmal berechne halt den Stack overflow. Wenn ich erst ein Feld berechne, dann das ganze für zwei usw. geht die Berechnung noch etwas weiter, aber auch hier kommt irgendwann der Overflow.

mfG
Visum
Udontknow
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2596

Win7
D2006 WIN32, .NET (C#)
BeitragVerfasst: Mi 18.09.02 08:40 
Hi!

Setze die maximale Stackgrösse einfach hoch:
ausblenden Quelltext
1:
{$MAXSTACKSIZE Stackgroesse}					


Eine weitere Möglichkeit ist das Umformen des Algorithmus in eine iterative Form, wo du dann eben dir einen eigenen Stack basteln muss (z.B. über das TStack-Objekt).

BTW: Wofür brauchst du das eigentlich? Das sieht interessant aus. :)

Cu, :D
Udontknow
Visum Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 106



BeitragVerfasst: Mi 18.09.02 17:13 
Hi,
den Stack zu vergrößern wäre schonmal nicht schlecht (glaube ich). Es wäre auf jeden Fall einen Versuch wert, da mir keine iterative Möglichkeit einfällt (vielleicht kommt das ja noch ;) ).

Aber wo muss ich das Maxstacksize hinschreiben?

visum
Udontknow
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2596

Win7
D2006 WIN32, .NET (C#)
BeitragVerfasst: Do 19.09.02 07:24 
Hi!

Schreibe es einfach in den Interface-Teil (d)einer Unit, das sollte reichen.

Cu,
Udontknow
Visum Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 106



BeitragVerfasst: Do 19.09.02 16:36 
Hab es direkt unter das
{R *.dfm} (oder so ;) )geschrieben.

Funktioniert so aber leider nicht.

Wie groß darf der Stack denn maximal sein? Ich hab ihn einfach immer nur verdoppelt, wenn ein Stack overflow kam (1MB, dann 2 ... bis 128).

Würde es den Stack "schonen", wenn ich anstelle des Arrays[1..16,1..10] einen String (bis zu 160 Zeichen) übergebe und dann eine weitere Prozedur einbaue?
Udontknow
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2596

Win7
D2006 WIN32, .NET (C#)
BeitragVerfasst: Fr 20.09.02 08:34 
Hi!

Hör mal, ein Array-Typ ist kein Objekt! Davon gehst du aber anscheinend aus (ein p wie Pointer bei pFeld). Wenn du deine Prozdur rekursiv so aufrufst, wird immer wieder eine Array-Version auf den Stack gehoben, Änderungen werden am ursprünglichen Array aber keine vorgenommen.

Übergib doch besser einen Zeiger auf das Feld, das schont den Stack, und du arbeitest dann auch in den rekursiv aufgerufenen Funktionen nur auf einem Feld und erzeugst nicht für jede Rekursion ein eigenes Array.

BTW: Ich sagte "Interface-Teil", {$R *.dfm} ist jedoch im Implementationsteil... Aber obs ne Rolle spielt, weiss ich auch nicht, also... :wink:

Cu, :D
Udontknow
Visum Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 106



BeitragVerfasst: Fr 20.09.02 14:27 
Hi,
p steht hier nicht für Pointer, sondern für einfach für Parameter (hat unser Lehrer mal so festgelegt und das ist halt hängengeblieben).

Das array muss hier aber für jeden Durchlauf anders sein (halt entstanden aus dem vorherigen).
Im ursprünglichen Array werden wirklich keine Änderungen vorgenommen. Aber in dem übergebenen in der Prozedur. So entsteht für jeden Prozedur-Aufruf ein neues Array.
Wenn ich das ganze global deklarieren würde, würde das Programm nicht mehr das tun, was es denn tun soll.
Und mit Zeigern kenn ich mich leider noch nicht aus.
Wie übergeb ich einen Zeiger?
Und würde das den gleichen Effekt haben, wie wenn ich das komplette Array übergebe, oder wäre es einem globalen Array gleich?

@Interface: Macht keinen Unterschied, es läuft in beiden Versionen nicht (der Stack overflow bleibt :( ).

visum
Udontknow
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2596

Win7
D2006 WIN32, .NET (C#)
BeitragVerfasst: Fr 20.09.02 14:58 
Hmpf... Sag deinem Lehrer mal, daß eine Variable pIrgendwas von jedem Programmierer auf der Welt erstmal sofort als Pointer betrachtet wird...

Was soll denn das Programm überhaupt tun? Ich kann so nicht gerade viel helfen... Aber irgendwo muss da noch ein Fehler sein. Die Rekursion dürfte ja eigentlich dann nur zu einer Tiefe gleich dem in der Variable Anzahl gespeicherten Wertes führen. Zeig mal bitte auch die Definition von TFeld.

Cu,
Udontknow