Search code examples
vb.netvisual-studiostack-overflow

Stuck with an odd stack overflow


I'm writing this program in Visual Basic .NET to organize different fields of data, and I'm using profile slots through application settings to store the data for users. But, I ran into a stack overflow error in my SlotSelect.vb class. My best plausible guess for why this happens is that I'm using the wrong kind of variable container in the below sauce code, but my dilemma is that I don't know what specifically is going wrong.

The code that the vshost is saying is the cause for the overflow was written from some code that I looked up on MSDN and other places for referring to objects in other classes, and I tried using other variants of it to see if it was any different. So far, nothing has worked, and it doesn't stop the error while compiling, much less in the code markup--it only catches it when it starts the application in debug after it finishes building.

Here's the sauce code for SlotSelect.vb. Since most of the other unrelated classes (and this one) lead into MainForm.vb, I'll include its sauce too. The location vshost gave as the error is on the line where variable _MainForm is defined for Flaglister.MainForm to be used within SlotSelect.vb.

SlotSelect.vb

Public Class SlotSelect

    ' Class variables
    Private _MainForm As Flaglister.MainForm = New Flaglister.MainForm
    Private _SaveSlot As Flaglister.SaveSlot = New Flaglister.SaveSlot
    Private _Misc As Flaglister.Misc = New Flaglister.Misc
    Private _FlagsTextBox As System.Windows.Forms.TextBox = Flaglister.MainForm.FlagsTextBox
    Private _VarsTextBox As System.Windows.Forms.TextBox = Flaglister.MainForm.VarsTextBox
    Private _HackNameTextBox As System.Windows.Forms.TextBox = Flaglister.MainForm.HackNameTextBox
    Private _RomCodeTextBox As System.Windows.Forms.TextBox = Flaglister.MainForm.RomCodeTextBox
    Private _NotesTextBox As System.Windows.Forms.TextBox = Flaglister.MainForm.NotesTextBox
    Private _ExpandedCheckBox As System.Windows.Forms.CheckBox = Flaglister.MainForm.ExpandedCheckBox

    ' Slot selection main execution subs
    Friend Sub _0()
        Try
            ' Disable FlagsTextBox
            _FlagsTextBox.DeselectAll()
            _FlagsTextBox.ClearUndo()
            _FlagsTextBox.Clear()
            _FlagsTextBox.Enabled = False
            ' Disable VarsTextBox
            _VarsTextBox.DeselectAll()
            _VarsTextBox.ClearUndo()
            _VarsTextBox.Clear()
            _VarsTextBox.Enabled = False
            ' Disable HackNameTextBox
            _HackNameTextBox.DeselectAll()
            _HackNameTextBox.ClearUndo()
            _HackNameTextBox.Clear()
            _HackNameTextBox.Enabled = False
            ' Disable RomCodeTextBox
            _RomCodeTextBox.DeselectAll()
            _RomCodeTextBox.ClearUndo()
            _RomCodeTextBox.Clear()
            _RomCodeTextBox.Enabled = False
            ' Disable NotesTextBox
            _NotesTextBox.DeselectAll()
            _NotesTextBox.ClearUndo()
            _NotesTextBox.Clear()
            _NotesTextBox.Enabled = False
        Catch
            Call _Misc.ErrorClose()
        End Try
    End Sub
    Friend Sub _1()
        Try
            ' Load flaglist
            _FlagsTextBox.DeselectAll()
            _FlagsTextBox.ClearUndo()
            _FlagsTextBox.Clear()
            _FlagsTextBox.Enabled = True
            _FlagsTextBox.Text = My.Settings.Flaglist_1
            ' Load varlist
            _VarsTextBox.DeselectAll()
            _VarsTextBox.ClearUndo()
            _VarsTextBox.Clear()
            _VarsTextBox.Enabled = True
            _VarsTextBox.Text = My.Settings.Varlist_1
            ' Load project name
            _HackNameTextBox.DeselectAll()
            _HackNameTextBox.ClearUndo()
            _HackNameTextBox.Clear()
            _HackNameTextBox.Enabled = True
            _HackNameTextBox.Text = My.Settings.Hackname_1
            ' Load ROM codename
            _RomCodeTextBox.DeselectAll()
            _RomCodeTextBox.ClearUndo()
            _RomCodeTextBox.Clear()
            _RomCodeTextBox.Enabled = True
            _RomCodeTextBox.Text = My.Settings.Romcode_1
            ' Load other notes
            _NotesTextBox.DeselectAll()
            _NotesTextBox.ClearUndo()
            _NotesTextBox.Clear()
            _NotesTextBox.Enabled = True
            _NotesTextBox.Text = My.Settings.Notes_1
        Catch
            Call _Misc.ErrorClose()
        End Try
    End Sub
    Friend Sub _2()
        Try
            ' Load flaglist
            _FlagsTextBox.DeselectAll()
            _FlagsTextBox.ClearUndo()
            _FlagsTextBox.Clear()
            _FlagsTextBox.Enabled = True
            _FlagsTextBox.Text = My.Settings.Flaglist_2
            ' Load varlist
            _VarsTextBox.DeselectAll()
            _VarsTextBox.ClearUndo()
            _VarsTextBox.Clear()
            _VarsTextBox.Enabled = True
            _VarsTextBox.Text = My.Settings.Varlist_2
            ' Load project name
            _HackNameTextBox.DeselectAll()
            _HackNameTextBox.ClearUndo()
            _HackNameTextBox.Clear()
            _HackNameTextBox.Enabled = True
            _HackNameTextBox.Text = My.Settings.Hackname_2
            ' Load ROM codename
            _RomCodeTextBox.DeselectAll()
            _RomCodeTextBox.ClearUndo()
            _RomCodeTextBox.Clear()
            _RomCodeTextBox.Enabled = True
            _RomCodeTextBox.Text = My.Settings.Romcode_2
            ' Load other notes
            _NotesTextBox.DeselectAll()
            _NotesTextBox.ClearUndo()
            _NotesTextBox.Clear()
            _NotesTextBox.Enabled = True
            _NotesTextBox.Text = My.Settings.Notes_2
        Catch
            Call _Misc.ErrorClose()
        End Try
    End Sub
    Friend Sub _3()
        Try
            ' Load flaglist
            _FlagsTextBox.DeselectAll()
            _FlagsTextBox.ClearUndo()
            _FlagsTextBox.Clear()
            _FlagsTextBox.Enabled = True
            _FlagsTextBox.Text = My.Settings.Flaglist_3
            ' Load varlist
            _VarsTextBox.DeselectAll()
            _VarsTextBox.ClearUndo()
            _VarsTextBox.Clear()
            _VarsTextBox.Enabled = True
            _VarsTextBox.Text = My.Settings.Varlist_3
            ' Load project name
            _HackNameTextBox.DeselectAll()
            _HackNameTextBox.ClearUndo()
            _HackNameTextBox.Clear()
            _HackNameTextBox.Enabled = True
            _HackNameTextBox.Text = My.Settings.Hackname_3
            ' Load ROM codename
            _RomCodeTextBox.DeselectAll()
            _RomCodeTextBox.ClearUndo()
            _RomCodeTextBox.Clear()
            _RomCodeTextBox.Enabled = True
            _RomCodeTextBox.Text = My.Settings.Romcode_3
            ' Load other notes
            _NotesTextBox.DeselectAll()
            _NotesTextBox.ClearUndo()
            _NotesTextBox.Clear()
            _NotesTextBox.Enabled = True
            _NotesTextBox.Text = My.Settings.Notes_3
        Catch
            Call _Misc.ErrorClose()
        End Try
    End Sub


    ' Save all slots
    Friend Sub SlotSaveAll()
        Call _SaveSlot.FlaglistSave()
        Call _SaveSlot.VarlistSave()
        Call _SaveSlot.HacknameSave()
        Call _SaveSlot.RomcodeSave()
        Call _SaveSlot.NotesSave()
        Call _SaveSlot.ExpandedSave()
    End Sub
End Class

MainForm.vb

Public Class MainForm

    ' Class-level variables
    Private _SlotSelect As New Flaglister.SlotSelect
    Private _SaveSlot As New Flaglister.SaveSlot
    Private _Misc As New Flaglister.Misc

    ' Startup/Shutdown events
    Sub MainForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        If Slot0RadioButton.Checked = True Then
            Call _SlotSelect._0()
        End If
    End Sub
    Sub MainForm_Deactivate(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Deactivate
        My.Settings.Save()
        Me.Close()
    End Sub

    ' Form object events
    Private Sub Slot0RadioButton_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Slot0RadioButton.CheckedChanged
        If Slot0RadioButton.Checked = True Then
            Call _SlotSelect._0()
        End If
    End Sub
    Private Sub Slot1RadioButton_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Slot1RadioButton.CheckedChanged
        If Slot1RadioButton.Checked = True Then
            Call _SlotSelect._1()
        End If
    End Sub
    Private Sub Slot2RadioButton_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Slot2RadioButton.CheckedChanged
        If Slot2RadioButton.Checked = True Then
            Call _SlotSelect._2()
        End If
    End Sub
    Private Sub Slot3RadioButton_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Slot3RadioButton.CheckedChanged
        If Slot3RadioButton.Checked = True Then
            Call _SlotSelect._3()
        End If
    End Sub
    Private Sub FlagsTextBox_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles FlagsTextBox.TextChanged
        Call _SaveSlot.FlaglistSave()
    End Sub
    Private Sub VarsTextBox_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles VarsTextBox.TextChanged
        Call _SaveSlot.VarlistSave()
    End Sub
    Private Sub HackNameTextBox_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles HackNameTextBox.TextChanged
        Call _SaveSlot.HacknameSave()
    End Sub
    Private Sub RomCodeTextBox_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RomCodeTextBox.TextChanged
        Call _SaveSlot.RomcodeSave()
    End Sub
    Private Sub NotesTextBox_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles NotesTextBox.TextChanged
        Call _SaveSlot.NotesSave()
    End Sub
    Private Sub ExpandedCheckBox_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ExpandedCheckBox.CheckedChanged
        Call _SaveSlot.ExpandedSave()
    End Sub
End Class

What's the problem in the code?

Here's some additional details about me and my program.

Computer

System: Seven x64 w/ AMD Sempron
Compiler: Microsoft Visual Basic 2010 Express

Application

Framework: Microsoft .NET version 3.5
Root Namespace: Flaglister
Assembly name: Flaglister
Application Type: Windows Forms Application

Sometimes I think too much, so I'm sorry if the answer is obvious to many and I don't see it.

EDIT

Here's a screenshot of the callstack at its current position when the error is thrown, and another screenshot of the popup error box. I would've never guessed to add these.

Call stack screenshot

Exception screenshot


Solution

  • The issue here is recursive initialization. MainForm contains:

    Private _SlotSelect As New Flaglister.SlotSelect
    

    And SlotSelect contains:

    Private _MainForm As Flaglister.MainForm = New Flaglister.MainForm
    

    They keep calling each other's constructor, causing your stack overflow. You can fix this by passing in _MainForm as an argument in SlotSelect's constructor. Like so:

    Public Class SlotSelect
    
        ' Class variables
        Private _MainForm As Flaglister.MainForm
        ' (truncated for space)
    
        Public Sub New(ByVal mainForm As Flaglister.MainForm)
            Me._MainForm = mainForm
        End Sub
    
        '...
    

    And in MainForm.vb, pass SlotSelect's constructor the current instance:

    Private _SlotSelect As New Flaglister.SlotSelect(Me)