Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - Stacküberlauf bei Division


Bronstein - Mi 14.03.07 15:23
Titel: Stacküberlauf bei Division
Ich bekomme seit ich den folgenden Code in mein Programm eingefügt habe immer eine Fehlermeldung mit Stack-Überlauf.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
var
  i: Integer;
  tmpFloat: Extended;
[...]

  i := Nachtschicht[0] + Fruehschicht[0] + Spaetschicht[0];
    tmpFloat := Nachtschicht[0] + Nachtschicht[1] + Fruehschicht[0] + Fruehschicht[1] + Spaetschicht[0] + Spaetschicht[1];
    tmpFloat := i / (tmpFloat / 100);
    frmSpea.Series13.Add(tmpFloat, tmpBeschriftung);


Lasse ich aber diese Zeile weg. Kommt die Meldung nicht, was mache ich bei dieser Zeile falsch??

Delphi-Quelltext
1:
tmpFloat := i / (tmpFloat / 100);                    


Backslash - Mi 14.03.07 15:33

Ich geh mal davon aus, dass du mit statischen Arrays arbeitest. Die werden meines Wissens >>IMMER<< über den Programmstack verwaltet. Da reicht schon ein einfaches....


Delphi-Quelltext
1:
2:
var
  Ar : array[0..200000000of Integer;


für einen Stacküberlauf aus. Hier wird sofort bei Initialisierung des Arrays der Fehler auftreten, weil du richtig viel Stackspeicherplatz dafür brauchst.

Hier ein paar Lösungsansätze:

1. Den Programmstack über die Compiler- bzw. Projektoptionen vergrößern (nur in seltenen Fällen empfehlenswert).

2. Mit dynamischen Arrays arbeiten. Wie das geht, erfährst du hier im Forum wenn du danach suchst. Ein dynamisches Array initialisierst du mit "SetLength".

Beispiel:

Delphi-Quelltext
1:
2:
3:
4:
5:
var
  Ar : array of Integer; // reine Arraydeklaration
begin
  Setlength(Ar, 200000);
end;


Vorteile: Das Array wird nicht maßgeblich über den Programmstack verwaltet, sondern nur der Zeiger auf das Array (ich hoffe das ist korrekt, wenn nicht dann möge mich jemand verbessern :)). Zudem kannst du die Arraygröße zur Laufzeit jederzeit neu bestimmen.


Bronstein - Mi 14.03.07 15:41

Ich habe die Arrays jetzt mal so deklariert, das funktioniert auch nicht


Delphi-Quelltext
1:
2:
3:
4:
5:
var Fruehschicht, Spaetschicht, Nachtschicht: array of Integer; 
begin
  Setlength(Nachtschicht, 6);
  Setlength(Fruehschicht, 6);
  Setlength(Spaetschicht, 6);


zu vor waren sie so deklariert

Delphi-Quelltext
1:
var Fruehschicht, Spaetschicht, Nachtschicht: array[0..5of Integer;                    


daran liegt es also nicht


Backslash - Mi 14.03.07 16:05

Hm... Die Arrays sind zu klein. Daran kann es wirklich nicht liegen. Dann empfehle ich dir, mal den ProgrammStack zu vergrößern (alte Stackgröße später wieder zurücksetzen) um zu testen ob der Fehler erstmal nicht mehr auftritt.

Wie es aussieht, scheint dein Programm den Stack an irgend einer anderen Stelle zu überlasten und lediglich hier kommt es dann zum großen "Gau".

Gibt es irgendwo eine Stelle im Programm wo du mit mords großen Arrays arbeitest? Du kannst auch einen Stacküberlauf erzeugen, wenn eine Funktion sich rekursiv immer wieder mit einer Kopie von einem Array beispielsweise aufruft (Arraytyp nicht als Varparameter übergeben wird). Wenn da noch so eine Stelle existiert, dann würde ich dir empfehlen das kurz mitzuteilen. Vielleicht kann ich oder jemand anders dir helfen.

Gruß

Backslash


Bronstein - Mi 14.03.07 16:16

Ich habe bei meinem Code eigentlich nur die obigen Zeilen eingefügt, zuvor ist der Fehler nicht aufgetreten.

Die Funktion wird auch nur über einen Button aufgerufen, somit ist auch ausgeschlossen, dass die Arrays immer neu erstellt werden.

Wie kann ich den ProgrammStack vergrößern?


Backslash - Mi 14.03.07 16:29

Ok da fällt mir nochwas auf.

Auf welchen Komponententyp "frmSpea.Series13.Add(tmpFloat, tmpBeschriftung);" zu? (TSeries???)


Vielleicht kommt bei "tmpFloat := i / (tmpFloat / 100);" ein Wert raus, den das "Add" der Series13 nicht verträgt und intern dann einen Stacküberlauf erzeugt.

In meinem Delphi 2005 (nur dafür kann ich dir jetzt leider sagen wie es mit dem Stack geht) kann ich den Programmstack über den Menüpunkt "Projekt/Optionen" und dann im Reiter "Linker" verändern. Dann erscheinen zwei Felder für die Stackgröße die du verändern kannst "Minimale Größe" und "Maximale Größe". In deinem Fall die maximale Größe. Aber daran denken den alten Maximal-Stackwert zu notieren und das ganze später rückgängig zu machen und den alten Wert wieder einzutragen. Bei mir enthält die maximale Stackgröße "$00100000". Bei Stackproblemen die ich so nicht ermitteln kann, verschiebe ich die 1 einfach solange um 1 nach links bis der Fehler nicht mehr auftritt.

Tritt der Fehler bei vergrößertem Stack nicht mehr auf, handelt es sich wahrscheinlich um ein kleineres Problem.


Bronstein - Mi 14.03.07 17:28

Danke, es lag an dem Wert das ich bei der Series eingebügt habe. Runde ich diesen mit Trunc, dann funktioniert es