超出字符串空间 - <out of =“”memory =“”>错误</out>

时间:2013-08-08 19:26:02

标签: variables vb6 out-of-memory

我有一个复杂的代码,但总结一下,我有这个:

名为RecordSet的{​​{1}};
名为rstRecords的全局string变量;
名为StrLetters的{​​{1}}变量,每次运行string时都有StrText个内容;
一个different

每次loop转到While Loop时,它都会loop。喜欢:

next

当它有大量记录,并且您将鼠标放在变量Add more content to the string StrLetters上时,它会显示此工具提示Do While Not rstRecords.EOF 'Codes Here Here I call a method named FeedLetter, that has lot of codes but also feed this string Loop Private Sub FeedLetter() 'Lot of code 'And Here I feed that string StrLetters = StrLetters + StrText End Sub 。以下错误StrLetters

<Out Of Memory>结束时,方法将使用String Out of Space的值并在纸张上打印。

我知道它被解雇了,因为在loop中变量有StrLetters 我想知道一种解决这个问题的方法......

更新

这是错误发生的地方(Dave给出的VB6方法)。

我打电话:

Max Lengh Value

错误发生在这里:

cStringBuilderClass

1 个答案:

答案 0 :(得分:1)

我无法找到我所指的那篇非常旧的Visual Basic Programmers Journal文章的链接。我将发布基于该文章创建的代码,并且多年来一直运行良好。

我真正喜欢这个实现的一个方面是它允许你设置缓冲区的初始大小。任何语言中任何StringBuilder / StringBuffer类中最慢的部分(具有不可变的字符串,如VB6,VB.Net,C#,Java等),都必须调整自身大小以适应新添加或插入的文本。如果你可以很好地猜测最终字符串的大小,你可以在开始之前(或者在任何时候真的)调用EnsureCapacity方法,以便在一次调用中使缓冲区成为合适的大小。

在您的情况下,如果您可以找出RecordSet中有多少行,并将其乘以要添加的平均大小字符串,您将获得对最终字符串大小的粗略估计。在调用EnsureCapacity时使用该值。您还可以设置在必须扩展缓冲区时将使用的增量大小。在我的代码中,缓冲区增加了64个字符块。例如,如果您知道每个Append操作将是~1500个字符,那么将CapacityIncrement属性设置为至少1500,因为这将更快。我仍然建议使用我描述的最终字符串大小方法。

Option Explicit

Private m_str As String
Private m_lngLength As Long             ' Current length (char count)
Private m_lngCapacity As Long           ' Current capacity (length of buffer)
Private m_lngCapacityIncrement As Long  ' Number of characters to add when incrementing capacity

Private Sub Class_Initialize()
   m_lngCapacityIncrement = 64
End Sub

Public Sub Append(ByVal str As String)
Dim lngLen As Long
   lngLen = Len(str)
   If lngLen = 0 Then Exit Sub
   EnsureCapacity (m_lngLength + lngLen)
   Mid$(m_str, m_lngLength + 1, lngLen) = str
   m_lngLength = m_lngLength + lngLen
End Sub

Public Property Get Capacity() As Long
   Capacity = m_lngCapacity
End Property

Public Property Get CapacityIncrement() As Long
   CapacityIncrement = m_lngCapacityIncrement
End Property

Public Property Let CapacityIncrement(ByVal lngNewValue As Long)
   If lngNewValue > 0 Then m_lngCapacityIncrement = lngNewValue
End Property

Public Sub EnsureCapacity(ByVal lngMinimum As Long)
Dim lngDiff As Long
   If ((m_lngCapacity < lngMinimum) And (lngMinimum > 0)) Then
      ' If current capacity isn't enough, then figure out how many capacity increments you need to meet
      ' the given minimum
      lngDiff = lngMinimum - m_lngCapacity
      If (lngDiff < m_lngCapacityIncrement) Then
         ' The If...ElseIf... is quicker than the math in the ElseIf
         lngDiff = m_lngCapacityIncrement
      ElseIf (lngDiff > m_lngCapacityIncrement) Then
         ' Note that the division is using \ operator instead of /.  \ truncates decimal part
         lngDiff = ((lngDiff \ m_lngCapacityIncrement) + 1) * m_lngCapacityIncrement
      End If
      m_str = m_str & String$(lngDiff, vbNullChar)
      m_lngCapacity = (m_lngCapacity + lngDiff)
   End If
End Sub

Public Property Get Length() As Long
   Length = m_lngLength
End Property

Public Function GetString() As String
   GetString = left$(m_str, m_lngLength)
End Function

Public Sub Reset()
   m_str = ""
   m_lngLength = 0
   m_lngCapacity = 0
   m_lngCapacityIncrement = 64
End Sub