Search code examples
vb.netloopsstack-overflowinfinite-loopmscorlib

Getting StackOverflowException in a loop


I made a application to test the Martingale strategy, but I am getting this annoying exception in my app while running.

Full application code for testing:

Module Module1

Dim basebet, balance, rollunder, sleep As Integer
Dim increaseby As Decimal
Dim bet As Decimal

Dim confTarget As Integer

Sub Main()
    bootConf()
    Menu()
End Sub

Sub bootConf()

    basebet = 1          '1 Base Bet
    bet = 1              'Current Bet
    increaseby = 3       'Multiplier on loss
    balance = 50000      '100 Starting Balance
    rollunder = 4998     '1% House Edge
    sleep = 50           'Sleep between bets in MS

End Sub

Sub basebetConf(ByVal newVal As Integer)
    basebet = newVal
    Conf()
End Sub
Sub increasebyConf(ByVal newVal As Integer)
    increaseby = newVal
    Conf()
End Sub
Sub balanceConf(ByVal newVal As Integer)
    balance = newVal
    Conf()
End Sub
Sub rollunderConf(ByVal newVal As Integer)
    If newVal > 4999 Then
        Conf()
    ElseIf newVal < 1 Then
        Conf()
    Else
        rollunder = newVal
        Conf()
    End If
End Sub
Sub sleepConf(ByVal newVal As Integer)
    sleep = newVal
    Conf()
End Sub

Sub Conf()
    Console.Clear()
    Console.WriteLine("")
    Console.WriteLine("                                 Martingale Simulator")
    Console.WriteLine("                                 Developed by Art3mis")
    Console.WriteLine("")
    Console.WriteLine("                               CONFIGURATION")
    Console.WriteLine("                               ¯¯¯¯¯¯¯¯¯¯¯¯¯")
    Console.WriteLine("                               BASE BET            : " & basebet)
    Console.WriteLine("                               LOSE MULTIPLIER     : " & increaseby)
    Console.WriteLine("                               BASE BALANCE        : " & balance)
    Console.WriteLine("                               ROLLUNDER (0-5000)  : " & rollunder)
    Console.WriteLine("                               SLEEP (IN MILLISEC) : " & sleep)
    Console.WriteLine("")
    Console.WriteLine("                                 Select value to edit (1-5)")
    Console.WriteLine("                                 Press X to return.")
    Console.Write("                                     > ")
    Dim input As ConsoleKeyInfo = Console.ReadKey()
    If input.Key = ConsoleKey.D1 Then
        confTarget = 1
    ElseIf input.Key = ConsoleKey.D2 Then
        confTarget = 2
    ElseIf input.Key = ConsoleKey.D3 Then
        confTarget = 3
    ElseIf input.Key = ConsoleKey.D4 Then
        confTarget = 4
    ElseIf input.Key = ConsoleKey.D5 Then
        confTarget = 5
    ElseIf input.Key = ConsoleKey.X Then
        Menu()
    Else
        Conf()
    End If
    Console.WriteLine("")
    Console.WriteLine("")
    Console.WriteLine("                                 Enter new value")
    Console.WriteLine("                                 Press X to return.")
    Console.Write("                                     > ")
    Dim input2 As Integer = Console.ReadLine()
    If confTarget = 1 Then
        basebetConf(input2)
    ElseIf confTarget = 2 Then
        increasebyConf(input2)
    ElseIf confTarget = 3 Then
        balanceConf(input2)
    ElseIf confTarget = 4 Then
        rollunderConf(input2)
    ElseIf confTarget = 5 Then
        sleepConf(input2)
    End If
        'Console.Read()

End Sub

Sub Menu()
    Console.Clear()
    Console.WriteLine("")
    Console.WriteLine("                                 Martingale Simulator")
    Console.WriteLine("                                 Developed by Art3mis")
    Console.WriteLine("")
    Console.WriteLine("                              ╔═ MENU ═════════════════╗")
    Console.WriteLine("                              ╠═ 1 : START             ║")
    Console.WriteLine("                              ╠═ 2 : CONFIGURATION     ║")
    Console.WriteLine("                              ╠═ 3 : ABOUT & CREDITS   ║")
    Console.WriteLine("                              ╚════════════════════════╝")
    Console.Write("                              > ")
    Dim input As ConsoleKeyInfo = Console.ReadKey()
    If input.Key = ConsoleKey.D1 Then
        Console.Clear()
        Console.WriteLine("")
        Console.WriteLine("                                 Martingale Simulator")
        Console.WriteLine("                                 Developed by Art3mis")
        Console.WriteLine("")
        Roll()
    ElseIf input.Key = ConsoleKey.D2 Then
        Conf()
    ElseIf input.Key = ConsoleKey.D3 Then
        About()
    Else
        Menu()
    End If


End Sub

Sub Roll()
    Dim rn As New Random
    Dim roll As Integer
    roll = rn.Next(0, 10000)
    If roll > rollunder Then
        'Console.ForegroundColor = ConsoleColor.Red
            Console.WriteLine("LOSE - " & roll & " - Bet: " & bet)
        'Console.ResetColor()
            balance -= bet
            bet = bet * increaseby
            Console.Title = "Martingale Sim - Balance: " & balance
    Else
        'Console.ForegroundColor = ConsoleColor.Green
            Console.WriteLine("WIN  - " & roll & " - Bet: " & bet)
        'Console.ResetColor()
            balance += bet
            bet = basebet
            Console.Title = "Martingale Sim - Balance: " & balance
    End If
    Threading.Thread.Sleep(sleep)
    checkRoll()
End Sub

Sub checkRoll()
    If balance < 0 Then
        MsgBox("Ran out of balance.")
    Else
        Roll()
    End If

End Sub

Sub About()


End Sub
End Module

Here's the spot where the application fails and throws the exception:

    If roll > rollunder Then
        'Console.ForegroundColor = ConsoleColor.Red
            Console.WriteLine("LOSE - " & roll & " - Bet: " & bet) *** HERE!
        'Console.ResetColor()
            balance -= bet
            bet = bet * increaseby
            Console.Title = "Martingale Sim - Balance: " & balance
    Else
        'Console.ForegroundColor = ConsoleColor.Green
            Console.WriteLine("WIN  - " & roll & " - Bet: " & bet) *** HERE!
        'Console.ResetColor()
            balance += bet
            bet = basebet
            Console.Title = "Martingale Sim - Balance: " & balance
    End If
    Threading.Thread.Sleep(sleep)
    checkRoll()

I'm aware that this happens because it's in a infinite loop. I didnt find anything to help me in this situation, so I don't really know what to do.

Here's a screenshot showing the bug: http://prntscr.com/aw7mqd

Thanks in advance!

A


Solution

  • To give an example of what @Maximilian is referring to, change your Roll and checkRoll methods to look something like the following, which avoids the need for recursion.

    Sub Roll()
        Do
            ...
        Loop While checkRoll()
    End Sub
    
    Function checkRoll() As Boolean
        If balance < 0 Then
            MsgBox("Ran out of balance.")
            Return False
        End If
        Return True
    End Function