Stack Overflow

Hallo Experten!

Ich habe einen Stack Overflow in meinem Projekt haengen.

Wenn eine bestimmte Prozedur aufgerufen wird stuerzt mein Program mit einer Stack Overflow Exception ab. (Reproduzierbar)

Komischerweise nicht wenn irgendeiner Variablen etwas zugewiesen wird (was mir das ganza Ding logischer machen wuerde).

Ich habe bereits probiert in den Projekt-Optionen die Stack-Groesse zu vergroessern, aber das nuetzt nix.

System: Borland C++ Builder 4, Win NT 4

Danke im Vorraus, Christof

Hallo Christof

Ich habe einen Stack Overflow in meinem Projekt haengen.

Wenn eine bestimmte Prozedur aufgerufen wird stuerzt mein
Program mit einer Stack Overflow Exception ab.
(Reproduzierbar)

Komischerweise nicht wenn irgendeiner Variablen etwas
zugewiesen wird (was mir das ganza Ding logischer machen
wuerde).

Ich habe bereits probiert in den Projekt-Optionen die
Stack-Groesse zu vergroessern, aber das nuetzt nix.

Ohne den Code der entsprechenden Prozedur ist dir nicht zu helfen !

Aber mal so zum nachdenken:

  1. Ist da was rekursiv ?
  2. Nicht initialisierte Zeiger, insbesondere als Auto-Variablen liefern fast immer sehr „schöne“ Ergebnisse (Der Zeiger ist dann mit Daten-Müll auf dem Stack inizialisiert, und je nach Programm steht an dieser Stelle immer der gleiche Schrott und das ganze ist reproduzierbar).
  3. Schalt mal Alles an Warnungen EIN, was der Compiler hergibt. Guter Code sollte auch dann ohne eine Warnung zu compilieren sein. Wenn man bewusst etwas macht, was der Compiler nicht versteht, so kann man mit einer #pragma-Anweisung die entsprechende Warnung vor diesem Code-Segment ab- und danach wieder einschalten, somit ist diese Stelle auch gleich als „etwas komisch“ markiert.

MfG Peter(TOO)

Ohne den Code der entsprechenden Prozedur ist dir nicht zu
helfen !

Is glaub zu gross fuer hier.

Aber mal so zum nachdenken:

  1. Ist da was rekursiv ?

Nix, nur eine Schleife, aber soweit kommt er gar nicht.

  1. Nicht initialisierte Zeiger, insbesondere als
    Auto-Variablen liefern fast immer sehr „schöne“ Ergebnisse
    (Der Zeiger ist dann mit Daten-Müll auf dem Stack
    inizialisiert, und je nach Programm steht an dieser Stelle
    immer der gleiche Schrott und das ganze ist reproduzierbar).

Keine nichtinitialisierten Zeiger.
Gestern hat es mir mal eine Weile lang ein char[255] ueberschrieben. (nicht Zeiger auf ein char-array, sondern echt reservierter Speicher) Als ich dann mal den Speicher mit dem Debugger ueberwacht habe hat er aufgehoert zu ueberschreiben.

  1. Schalt mal Alles an Warnungen EIN, was der Compiler
    hergibt. Guter Code sollte auch dann ohne eine Warnung zu
    compilieren sein.

Warnings bringt er keine, Compilereinstellung:
Warnings -> all

Wenn man bewusst etwas macht, was der
Compiler nicht versteht, so kann man mit einer
#pragma-Anweisung die entsprechende Warnung vor diesem
Code-Segment ab- und danach wieder einschalten, somit ist
diese Stelle auch gleich als „etwas komisch“ markiert.

Ist dafuer die #pragma-Anweisung?
Wieder was gelernt.

Danke, Christof

Mail doch mal das Proggie zu (den Source) mit allen Includes die man benötigt und die nicht standard sind.

Wenn das nicht magst, die Funktion mit erläufterung was sie bekommen muss.

Dann kan man sich das mal genauer anschaun.

Gruß

Micha

Mail doch mal das Proggie zu (den Source) mit allen Includes
die man benötigt und die nicht standard sind.

Danke fuer das Angebot, kann ich nur leider nicht annehmen.

Hallo Christof,

  1. Nicht initialisierte Zeiger, insbesondere als
    Auto-Variablen liefern fast immer sehr „schöne“ Ergebnisse
    (Der Zeiger ist dann mit Daten-Müll auf dem Stack
    inizialisiert, und je nach Programm steht an dieser Stelle
    immer der gleiche Schrott und das ganze ist reproduzierbar).

Keine nichtinitialisierten Zeiger.
Gestern hat es mir mal eine Weile lang ein char[255]
ueberschrieben. (nicht Zeiger auf ein char-array, sondern echt
reservierter Speicher) Als ich dann mal den Speicher mit dem
Debugger ueberwacht habe hat er aufgehoert zu ueberschreiben.

Grundsätzlich gibt es nur 3 Ursachen für einen Programmfehler:

  1. Bug ein deinem Source-Code.
  2. Bug in einem fremden Source (inkl. Compiler. Betriebssystem und Tools).
  3. Fehler in der Hardware.

Mit deinem anderen Posting „Speicher vor Schreibzugriffen schuetzen“ beweist du, dass es doch ein ungültiger Zeiger ist der die Probleme verursacht!
Wenn du das Programm mit dem Debugger startest, verschieben sich teilweise die Adressen, und wenn dein fehlerhafter Zeiger mit einem Festen falschen Wert arbeitet schreibt er dann in einen Bereich, welcher nicht benutzt wird und dein Programm funktioniert scheinbar fehlerfrei.
Mit gröster Wahrscheinlichkeit ligt das Problem nicht an einem Zugriff auf die „zerstörte“ Variable sondern ganz wo anders.
Ein Typisches Problem für nicht initialisierte Zeiger sind ungültige Zeiger und bei denen hat der Compiler keine Möglichkeit den Fehler zu enrkennen. z.B:

typ_Irgend_was *Igend_was;
Igend_was = new typ_Irgend_was;
Igend_was = wert;
delete Igend_was;
*Igend_was = irgend_ein_wert;

Mit „Igend_was = new typ_Irgend_was;“ wird „Igend_was“ freier Speicher zugewiesen. Nun kannst du mit „Igend_was“ alles erlaubte tun und die Speicherverwaltung garantiert dir, dass der zugewiesene Speicherbereich kein zweites mal zugewiesen wird.
Mit „delete Igend_was“ teilst du der Speicherverwaltung mit, dass der reservierte Bereich nicht mehr benötigt wird.
Du hast aber die Möglichkeit immer noch über „Igend_was“ auf den Speicherblock zuzugreifen. Wenn dieser Block nicht von der Speicherverwaltung für etwas anderes bereitgestellt wird wird auch alles, scheinbar fehlerfrei, funktionieren. Nur wenn jetzt die Speicherverwaltung diesen Speicherbereich für etwas anderes zugeteilt hat gibt es Probleme.

Um dem vorzubeugen ist es gute Praxis immer folgendes Konstrukt zu verwenden:

delete Igend_was;
Igend_was = NULL;

Hier besteht nun die Möglichkeit, dass die Laufzeitbibliothek den NULL-Zeiger erkennt und eine Fehlermeldung erzeugt.
Schwierig wird es bei folgendem Code

typ_Irgend_was *Igend_was;
typ_Irgend_was *noch_Igend_was;
Igend_was = new typ_Irgend_was;
Igend_was = wert;
noch_Igend_was = Igend_was;
delete Igend_was;
Igend_was = NULL;
*noch_Igend_was = irgend_ein_wert;

Hier nusst du aufpassen und auch die Kopie („noch_Igend_was“) mit dem NULL-Zeiger initialisieren.

MfG Peter(TOO)