VB.net中的堆栈溢出异常

时间:2011-04-05 22:15:32

标签: vb.net

我正在对今天的应用程序进行故障排除,定期运行以处理一些数据处理需求,它通常运行得很好,但有时应用程序会崩溃,有人必须手动重启它。

在查看源代码并进行一些调试之后,程序的核心似乎依赖于递归函数,该函数从DataTable中删除行,然后在DataTable不再有任何行剩余时停止。

以下是代码:

Public Sub ProcessData(ByRef dtTable As DataTable)
  Dim DataView1 As New DataView()
  Dim UID As String = ""
  Dim dtUID As New DataTable

  dtUID = dtTable.Clone()
  UID = dtTable.Rows(0)("UID")    

  DataView1 = dtTable.DefaultView

  Dim expression As String = "UID ='" & UID & "'"
  DataView1.RowFilter = expression

  For n As Integer = 0 To DataView1.Count - 1
      dtUID.ImportRow(DataView1.Item(n).Row)
  Next

  Dim foundRows() As DataRow
  foundRows = dtTable.Select(expression)

  For n As Integer = 0 To foundRows.GetUpperBound(0)
      dtTable.Rows.Remove(foundRows(n))
  Next

  For n As Integer = 0 To dtUID.Rows.Count - 1
      ProcessRecord(dtUID, n)
  Next

  If dtTable.Rows.Count > 0 Then
      ProcessData(dtTable)
  End If
End Sub

ProcessRecord()是一个将所有业务逻辑应用于记录并对数据库进行写入的函数。未处理的堆栈overFlow异常发生在:

For n As Integer = 0 To DataView1.Count - 1

在现实世界中,此函数将被输入DataTable,其中包含大约100,000条记录。在测试中,在堆栈溢出之前,经过多次试运行后,它将持续运行大约40,000-65,000。创建已经处理过的DataTableProcessRecord()标志记录的代码,因此如果您正在处理100,000个记录的大型数据集,则会在崩溃后对此方法进行后续调用较小的DataTable(35,000-60,000条记录。)有趣的是,堆栈溢出将越来越频繁地发生DataTables更小,我可以始终通过40k-65k的100k DataTable但不能始终如一在没有崩溃的情况下获得15k的15k DataTable(最终它将完成所有记录,在过去的几千次中发生多次崩溃。)

一旦我看到问题所在,我基本上废弃了大部分代码,并使用了我过去用于类似任务的实现。但我真的很想明白为什么这段代码导致了这个问题。

1 个答案:

答案 0 :(得分:2)

问题在于它是一个递归函数。

每个函数调用都使用堆栈空间来存储其参数和局部变量,并且堆栈空间有限。

没有理由这个特定的操作应该是递归的。事实上,当无法轻易估计或限制最大递归次数时,使用递归解决方案是个坏主意。