【问题标题】:StackOverFlowException was Unhandled on For LoopStackOverFlowException 在 For 循环上未处理
【发布时间】:2013-03-22 17:53:07
【问题描述】:

我刚刚使我的卡片选择动态化,而不是 5 个 if/elseif 语句的序列。

Private Sub PlayElse()
    Dim StartHeads As Integer
    Dim CardCheckBoxArray() As CheckBox = {CardCheckBox1, CardCheckBox2, CardCheckBox3, CardCheckBox4, CardCheckBox5, CardCheckBox6, CardCheckBox7, CardCheckBox8, CardCheckBox9, _
                                          CardCheckBox10, CardCheckBox11, CardCheckBox12, CardCheckBox13, CardCheckBox14, CardCheckBox15, CardCheckBox16, CardCheckBox17, _
                                          CardCheckBox18, CardCheckBox19, CardCheckBox20, CardCheckBox21, CardCheckBox22, CardCheckBox23, CardCheckBox24, CardCheckBox25}
    'Reset Number Generator
    Number = (DeckGroup(Rnd.Next(0, DeckGroup.Count)).ID)

    'card 1-5
    For StartHeads = 0 To 4
        If CardCheckBoxArray(StartHeads).Checked = True And DeckGroup(Number).QuantityInteger > 0 Then
            'Grab New Card From Deck
            DeckGroup(Number).QuantityInteger -= 1
            Player1HandGroup(Number).QuantityInteger += 1
            CardTypeArray(StartHeads) = Player1HandGroup(Number).CardType
            CardCheckBoxArray(StartHeads).Text = Player1HandGroup(Number).CardNameString
            NumberArray(StartHeads) = Number
        Else
            Call PlayElse()
        End If

这是我的原始代码(注意有一个 End If。我只是不想通过卡片 2-5 重复代码)

If CardCheckBox1.Checked = True And DeckGroup(Number).QuantityInteger > 0 Then
    'Grab New Card From Deck
    DeckGroup(Number).QuantityInteger -= 1
    Player1HandGroup(Number).QuantityInteger += 1
    CardTypeArray(0) = Player1HandGroup(Number).CardType
    CardCheckBox1.Text = Player1HandGroup(Number).CardNameString
    NumberArray(0) = Number

什么都没有真正改变,除了任何带 0 的点都没有由循环中的相应数字表示。我的项目中有几个与此类似的循环,但不知何故,这是一个获得 stackoverflow 异常的循环。 CardCheckBoxArray 中的 CardCheckBoxes 最多为 25,因为游戏中有 5 个玩家。在此特定语句中,任何超过 6 的 CardCheckBox 都不会被访问,因为此逻辑仅代表玩家 1 的牌。 (忘了说错误发生时继续按钮会导致子过程的顶部,突出显示Private Sub Playelse()。)

【问题讨论】:

  • 之前,你在Else里面也有Call PlayElse()吗?

标签: vb.net exception stack-overflow


【解决方案1】:

堆栈溢出异常的最常见原因(如这里的情况)是当您有一个递归方法调用自身太多次时。每次方法调用自身时,都会向堆栈添加更多数据。在方法退出之前,数据不会从堆栈中删除。例如,以下方法保证会抛出StackOverFlowException

Public Sub Fail(count As Integer)
    Fail(count + 1)
End Sub

如您所见,当Fail 方法(在我的示例中)被调用时,它会一遍又一遍地无限地调用自己,永远不会退出。因此,堆栈上的数据不断增长,直到最终耗尽空间并引发异常。

【讨论】:

  • 在程序找到匹配的 DeckGroup().QuantityInteger > 0 之前,没有任何东西被累积。我理解你的 sub,但在执行失败期间发生的只是声明 startheads 整数、cardcheck 数组, 生成一个新的随机数,然后检查玩家手中的牌 1-5 是否尚未填满。至少我是这样理解的。有没有办法在不溢出的情况下生成相同的结果,同时保留代码的动态特性?
【解决方案2】:

Sub PlayElseElse 的情况下递归调用自身。您始终必须确保递归在某个时间点终止,否则您将陷入无限递归并引发堆栈溢出异常。

If 条件表示... And DeckGroup(Number).QuantityInteger > 0。如果是这种情况,DeckGroup(Number).QuantityInteger 会递减。在某些时候它将为零,并且将执行 Else 案例,调用 PlayElse 将再次执行 Else 案例,因为 QuantityInteger 现在为零,依此类推。

应该将Call PlayElse() 放在Then 的末尾吗?

【讨论】:

  • 随机数生成器在子程序每次重启时都会生成一个“新”随机数。最终它遇到了 deckgroup().quantity 中大于 0 的项目,然后成功结束。这就是它从牌库中抓取特殊卡并将其放入玩家手中的方式。
  • 这意味着随机DeckGroup的数量将减少,但如果所有数量都是0,您仍然会得到无限递归。在调试器中单步执行该方法,您将看到会发生什么。
猜你喜欢
  • 1970-01-01
  • 2016-03-31
  • 1970-01-01
  • 2012-08-04
  • 1970-01-01
  • 2018-08-02
  • 2015-09-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多