Unerklärlicher Stackoverflow



  • Hallo,

    im Zuge der Erstellung einer Software stürzte diese bei einer bestimmten Aktion mit einer "StackOverflowException" ab. Da weder die Verschachtelungstiefe der Funktionen tief, noch eine Endlosrekursion erkennbar war, versuchte ich den entsprechenden Codeteil zu reduzieren um das Auslösen der Fehlermeldung zu isolieren. Es gelang mir zwar jenen Teil, der den Fehler verursacht, in ein eigenes minimales Testprogramm zu verschieben, allerdings die Erklärung fand ich nicht.

    Hier das komplette (sinnfreie) Testprogramm, welches sich nach dem klicken auf den Button mit einer "StackOverflowException" beendet:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            static volatile int Var = 0;
    
            void Test(int Val, Color Col) {}
    
            private void button1_Click(object sender, EventArgs e)
            {
                try {}
                catch
                {
                    Test(Var, Color.Black);
                }
            }
        }
    }
    

    Das wirklich interessante und umso unerklärlichere daran ist allerdings, dass das Programm ausschließlich unter Windows XP abstürzt. Unter Windows 7 oder 8 passiert nach dem klicken des Buttons erwartungsgemäß nichts. Programmiert wurde das mit dem "Visual Studio Express 2010 C#".

    Anbei noch ein Screeshot vom Absturz unter Windows XP (SP3):
    http://fs1.directupload.net/images/150205/m8kpy7vq.png

    Vielleicht kann mir jemand erklären was hier passiert und weshalb Windows 7 und 8 dagegen immun sind.

    Vielen Dank im Voraus.



  • Guck dir das mal in einem "mixed mode" Debugger an.
    Und welche .NET Runtime verwendest du? Und ist wirklich alles was du in dem Programm drinnen hast nötig um den Stack-Overflow zu triggern, oder kannst du noch 'was rauskürzen?



  • Danke für die Antwort.

    Ich habe versucht, das Testprogramm weiter zu vereinfachen, allerdings sind alle gegenwärtigen Codeteile notwendig, um einen Stack overflow zu provozieren. Entferne ich die Deklaration als 'static' oder/und als 'volatile' des Integer, oder übergebe ich nur den Integer und lasse die Farbe weg, dann wird kein Fehler mehr ausgelößt. Erstaunlicher weise stürzt das Programm nicht ab, wenn die Dummy-Funktion im try-Block steht. Ausschließlich im catch-Block, der so ja nie aufgerufen wird, verursacht diese Konstellation die Exception.

    Das Windows XP ist neu installiert und außer dem Visual Studio C# 2010 ist nichts installiert. Durch das Visual Studio C# 2010 ist das .net-Framework 4 mit installiert worden. Ein Test auf einem anderen Windows XP PC, auf dem ausschließlich das .net-Framework installiert ist, brachte ein ähnliches Ergebnis, das Programm beendet sich ohne explizite Fehlermeldung.

    Bringt das Visual Studio C# 2010 einen mixed mode Debugger mit?



  • Strange! Ändert eine 'catch' in 'catch (Exception ex)' Umwandlung was am verhalten?



  • Wie sieht denn der Stacktrace aus, d.h. welche Methode wird rekusiv aufgerufen?



  • Das Empfangen der Exception ändert nichts. Der Call-Stack sieht nach dem Klicken des Buttons wie folgt aus:

    http://fs1.directupload.net/images/150206/ha7ib2fd.png
    http://fs1.directupload.net/images/150206/td6dbidc.png



  • Der Stacktrace sieht mir aber nicht nach einer Rekursion aus.
    Evtl. ist der Stack zu klein? Dafür gibt es zwar keine Compileroption, aber ein externes Tool: editbin.exe - s. Increasing the Size of your Stack (.NET Memory Management: Part 3).

    Bei stackoverflow.com (passender Name 😉 finden sich einige weitere Beiträge zum Thema "XP StackoverflowException"...



  • Th69 schrieb:

    Der Stacktrace sieht mir aber nicht nach einer Rekursion aus.

    Siehst du was was ich nicht sehe?
    Im Stacktrace ist ja sogar das "ThreadHelper.ThreadStart" noch mit drinnen, und für micht sieht es so aus als wären auch alle Callstack-Zeilen sichtbar, da die Scrollbar ausgegraut ist.
    => Wohl eher doch keine Rekursion.

    EDIT: "nicht" übersehen 🙄



  • Hast du mir jetzt widersprochen oder doch nicht?



  • Erm.
    *self-facepalm*
    Ich hab das "nicht" überlesen.
    Nein, kein Widerspruch, bloss Unachtsamkeit meinerseits.



  • Danke für die Hinweise.

    Das Seltsame daran ist ja, dass die Funktion nicht aufgerufen wird und somit den Stack nicht zusätzlich belastet. Ich habe nun versuchte, die Größe des Stacks auszureizen und eine Rekursion der Funktion proviziert. Bei den selben Übergabeparametern (Integer und Color) bricht das Programm unter Windows XP erst bei einer Rekursionstiefe von etwa 9900 mit einem Stack-Overflow ab (siehe Bild). Insofern halte ich es fast für unmöglich, dass die Größe des Stacks bei einem einmaligen Aufruf der Funktion in dem catch-Block zu klein ist. Ist das möglicherweise ein Bug im .net-Framework oder/und Windows XP bei der Verwendung von mit static und volatile deklarierten Variablen in einem try-catch-Konstrukt?

    http://fs2.directupload.net/images/150209/gnq9i7aw.png



  • Übersetz doch mal mit unterschiedlichen Runtime Versionen!?!

    was passiert wenn du im try ein throw; machst?



  • Vielen Dank für diese Idee!

    Wenn ich bei dem Testprogramm nicht das, für das Visual Studio 2010 übliche, .net-Framework 4.0 als Zielframework auswähle, sondern das .net-Framework 3.5, dann tritt der Fehler nicht mehr auf! Nach dem klicken des Buttons passiert erwartungsgemäß nichts. Selbes Ergebnis wenn ich das .net-Framework 3.0 oder 2.0 auswähle (alle mit SP1), ebenso kein Stack-Overflow. Da die .net-Frameworks 2.0, 3.0 und 3.5 die CLR-Version 2.0 nutzen und erst das .net-Framework 4.0 die CLR-Version 4 nutzt, liegt es irgendwie nahe, dass die CLR-Version 4 einen Bug enthält.


Anmelden zum Antworten