被VB6这问题困惑了N久~热

时间:2022-07-13 23:15:37
用着用着就内存溢出,明明代码没错.翻译能OK~新打开时VB6就很快,后来调试调试着就越来越慢,慢到提示内存溢出而重新打开VB6,
这是什么问题呢.机器的内存有1G啊,再说VB6又没有VS2005那样占资源,C友们,这样的情况你们
有遇到吗------这可跟系统没关系哦--因为俺重装N次都会

16 个解决方案

#1


可能你的程序有很多对象使用后没有及时释放

#2


应该是你具体的代码问题。

#3


你是不是调用了什么API或者第三方控件,可能是资源没释放
  
*****************************************************************************
欢迎使用CSDN论坛专用阅读器 : CSDN Reader(附全部源代码) 
http://feiyun0112.cnblogs.com/

#4


这种问题不一定是内存占用太多:试一试下面的代码:
Private Sub Command1_Click()
Dim a As String
a = InStr(1, "12dザa", "a", 1)
End Sub

#5


老张,上面那个一启动就内存错误啊,俺那个不是这问题,
问下老张,俺使用对象后需要释放吗,俺好像使用后没有释放哦

#6


引用 1 楼 jhone99 的回复:
可能你的程序有很多对象使用后没有及时释放


好像没释放o

#7


LZ:你可在使用对象后用下面语句:
Nothing
使用 Nothing 关键字被将对象变量从实际对象中分离开来。要使用 Set 语句将 Nothing 赋值给对象变量。例如:

Set MyObject = Nothing

几个对象变量可以引用同一个实际对象。当 Nothing 被赋值给一个对象变量时,该变量不再引用任何实际对象。当几个对象变量引用同一个对象时,只有将全部对象变量都设置成 Nothing 之后,与被引用的对象有关联的内存资源及系统资源才会被释放掉,在这里,或者明确使用 Set,或者在最后一个设置成 Nothing 的对象变量超出范围后隐含地使用 Set。

#8


这叫内存泄漏,最常见的原因就是对象循环引用。看下面的例子

ParentClass
Option Explicit

Private m_Data(1023)

Public Child As ChildClass


ChildClass
Option Explicit

Private m_Data(1023)

Public Parent As ParentClass


Form1
添加控件 Label 两个、Timer、CheckBox、CommandButton
Option Explicit

Private m_LeakCount As Long
Private m_GoodCount As Long
Private m_NoLeak    As Boolean

Private Sub Test()
    Dim p As ParentClass, c As ChildClass
    
    Set p = New ParentClass
    Set c = New ChildClass
    
    Set p.Child = c
    Set c.Parent = p
    
    If m_NoLeak Then
        '内存泄漏的解决方法:解除循环引用
        Set p.Child = Nothing
        Set c.Parent = Nothing
    End If
    
    Set p = Nothing
    Set c = Nothing
End Sub

Private Sub Check1_Click()
    m_NoLeak = Check1.Value
End Sub

Private Sub Command1_Click()
    Timer1.Enabled = Not Timer1.Enabled
    Command1.Caption = IIf(Timer1.Enabled, "&Stop", "&Start")
End Sub

Private Sub Form_Load()
    Timer1.Enabled = False
    Timer1.Interval = 100
End Sub

Private Sub Timer1_Timer()
    Test
    If m_NoLeak Then
        m_GoodCount = m_GoodCount + 1
        Label2 = m_GoodCount
    Else
        m_LeakCount = m_LeakCount + 1
        Label1 = m_LeakCount
    End If
End Sub


如果 CheckBox 未选中,启动 Timer 后可以看到任务管理器中该进程的内存不停增长。
CheckBox 选中后就没有该问题了。

#9


引用 7 楼 zdingyun 的回复:
LZ:你可在使用对象后用下面语句: 
Nothing 
使用 Nothing 关键字被将对象变量从实际对象中分离开来。要使用 Set 语句将 Nothing 赋值给对象变量。例如: 

Set MyObject = Nothing 

几个对象变量可以引用同一个实际对象。当 Nothing 被赋值给一个对象变量时,该变量不再引用任何实际对象。当几个对象变量引用同一个对象时,只有将全部对象变量都设置成 Nothing 之后,与被引用的对象有关联的内存资源及系统资源才会被释放掉,…


是的.正如这位朋友所说.好多个窗体在Form_Unload中是用了Set Form1 = Nothing,因为好多窗体需要调用一个类,
那这样是正常还是错误呢,这位朋友能不能讲下~~谢谢了~!

#10


Tiger_Zhao兄台讲得好详细啊,太感谢了,俺要加分答谢~!

#11


引用 8 楼 Tiger_Zhao 的回复:
这叫内存泄漏,最常见的原因就是对象循环引用。看下面的例子 

ParentClass 
VB code
Option Explicit

Private m_Data(1023)

Public Child As ChildClass



ChildClass 
VB code
Option Explicit

Private m_Data(1023)

Public Parent As ParentClass



Form1 
添加控件 Label 两个、Timer、CheckBox、CommandButton 
VB code
Option Explicit

Private m_LeakCount As Long
Private m_GoodCount As Long
Private m_NoLeak …


Tiger_Zhao兄台这个好妙啊!

#12


引用 5 楼 IDtoID 的回复:
老张,上面那个一启动就内存错误啊,俺那个不是这问题, 
问下老张,俺使用对象后需要释放吗,俺好像使用后没有释放哦
释放引用对象当然可以减少内存的开销,不用一定要释放

#13


引用 12 楼 SYSSZ 的回复:
引用 5 楼 IDtoID 的回复:

老张,上面那个一启动就内存错误啊,俺那个不是这问题, 
问下老张,俺使用对象后需要释放吗,俺好像使用后没有释放哦 
释放引用对象当然可以减少内存的开销,不用一定要释放



原来还可以不一定要释放 谢谢老张 加分答谢

#14


无论是显式地 Set ... Nothing,还是隐式地通过变量的生命周期自动解除对象引用,都没有直接地“释放”对象,只是减少了对象的引用计数。
在 COM 机制中,只要引用计数归来,就自动释放对象。本来这是为了避免对象多处引用时被提前释放。
但是对象的循环引用恰恰是这种机制的软肋,越复杂的对象模型这个问题越难处理,.Net 框架就完全推翻改成了垃圾回收机制。

#15


明白了。这么说来VB6做的东西里面要是含带复杂的对象模型,那不是问题越多越难处理。
原来.Net是垃圾回收机制。

#16


复杂度其实是看如何设计对象之间的引用关系。
1)比如有两个对象:发票、明细,发票包含一组明细——那么发票肯定需要引用明细(通过集合或数组来包含),但是发票通常作为一个整体处理——明细不需要对发票进行引用;因此没有循环引用的问题。
2)在比如双向链表:很明细前后节点之间有引用,那么释放链表时需要拆开整个链表。
sub FreeDLink(byref pHeader as LinkNode)
    dim pThis as LinkNode, pNext as LinkNode
    set pThis = pHeader
    While Not pThis is nothing
        set pNext = pThis.NextNode
        set pThis.PrevNode = nothing
        set pThis.NextNode = nothing
        set pThis = pNext
    wend
    set pHeader = nothing
end sub


只要记得凡是有循环引用的对象,都需要用特定的方法显式释放就可以了。
一点也不复杂。

#1


可能你的程序有很多对象使用后没有及时释放

#2


应该是你具体的代码问题。

#3


你是不是调用了什么API或者第三方控件,可能是资源没释放
  
*****************************************************************************
欢迎使用CSDN论坛专用阅读器 : CSDN Reader(附全部源代码) 
http://feiyun0112.cnblogs.com/

#4


这种问题不一定是内存占用太多:试一试下面的代码:
Private Sub Command1_Click()
Dim a As String
a = InStr(1, "12dザa", "a", 1)
End Sub

#5


老张,上面那个一启动就内存错误啊,俺那个不是这问题,
问下老张,俺使用对象后需要释放吗,俺好像使用后没有释放哦

#6


引用 1 楼 jhone99 的回复:
可能你的程序有很多对象使用后没有及时释放


好像没释放o

#7


LZ:你可在使用对象后用下面语句:
Nothing
使用 Nothing 关键字被将对象变量从实际对象中分离开来。要使用 Set 语句将 Nothing 赋值给对象变量。例如:

Set MyObject = Nothing

几个对象变量可以引用同一个实际对象。当 Nothing 被赋值给一个对象变量时,该变量不再引用任何实际对象。当几个对象变量引用同一个对象时,只有将全部对象变量都设置成 Nothing 之后,与被引用的对象有关联的内存资源及系统资源才会被释放掉,在这里,或者明确使用 Set,或者在最后一个设置成 Nothing 的对象变量超出范围后隐含地使用 Set。

#8


这叫内存泄漏,最常见的原因就是对象循环引用。看下面的例子

ParentClass
Option Explicit

Private m_Data(1023)

Public Child As ChildClass


ChildClass
Option Explicit

Private m_Data(1023)

Public Parent As ParentClass


Form1
添加控件 Label 两个、Timer、CheckBox、CommandButton
Option Explicit

Private m_LeakCount As Long
Private m_GoodCount As Long
Private m_NoLeak    As Boolean

Private Sub Test()
    Dim p As ParentClass, c As ChildClass
    
    Set p = New ParentClass
    Set c = New ChildClass
    
    Set p.Child = c
    Set c.Parent = p
    
    If m_NoLeak Then
        '内存泄漏的解决方法:解除循环引用
        Set p.Child = Nothing
        Set c.Parent = Nothing
    End If
    
    Set p = Nothing
    Set c = Nothing
End Sub

Private Sub Check1_Click()
    m_NoLeak = Check1.Value
End Sub

Private Sub Command1_Click()
    Timer1.Enabled = Not Timer1.Enabled
    Command1.Caption = IIf(Timer1.Enabled, "&Stop", "&Start")
End Sub

Private Sub Form_Load()
    Timer1.Enabled = False
    Timer1.Interval = 100
End Sub

Private Sub Timer1_Timer()
    Test
    If m_NoLeak Then
        m_GoodCount = m_GoodCount + 1
        Label2 = m_GoodCount
    Else
        m_LeakCount = m_LeakCount + 1
        Label1 = m_LeakCount
    End If
End Sub


如果 CheckBox 未选中,启动 Timer 后可以看到任务管理器中该进程的内存不停增长。
CheckBox 选中后就没有该问题了。

#9


引用 7 楼 zdingyun 的回复:
LZ:你可在使用对象后用下面语句: 
Nothing 
使用 Nothing 关键字被将对象变量从实际对象中分离开来。要使用 Set 语句将 Nothing 赋值给对象变量。例如: 

Set MyObject = Nothing 

几个对象变量可以引用同一个实际对象。当 Nothing 被赋值给一个对象变量时,该变量不再引用任何实际对象。当几个对象变量引用同一个对象时,只有将全部对象变量都设置成 Nothing 之后,与被引用的对象有关联的内存资源及系统资源才会被释放掉,…


是的.正如这位朋友所说.好多个窗体在Form_Unload中是用了Set Form1 = Nothing,因为好多窗体需要调用一个类,
那这样是正常还是错误呢,这位朋友能不能讲下~~谢谢了~!

#10


Tiger_Zhao兄台讲得好详细啊,太感谢了,俺要加分答谢~!

#11


引用 8 楼 Tiger_Zhao 的回复:
这叫内存泄漏,最常见的原因就是对象循环引用。看下面的例子 

ParentClass 
VB code
Option Explicit

Private m_Data(1023)

Public Child As ChildClass



ChildClass 
VB code
Option Explicit

Private m_Data(1023)

Public Parent As ParentClass



Form1 
添加控件 Label 两个、Timer、CheckBox、CommandButton 
VB code
Option Explicit

Private m_LeakCount As Long
Private m_GoodCount As Long
Private m_NoLeak …


Tiger_Zhao兄台这个好妙啊!

#12


引用 5 楼 IDtoID 的回复:
老张,上面那个一启动就内存错误啊,俺那个不是这问题, 
问下老张,俺使用对象后需要释放吗,俺好像使用后没有释放哦
释放引用对象当然可以减少内存的开销,不用一定要释放

#13


引用 12 楼 SYSSZ 的回复:
引用 5 楼 IDtoID 的回复:

老张,上面那个一启动就内存错误啊,俺那个不是这问题, 
问下老张,俺使用对象后需要释放吗,俺好像使用后没有释放哦 
释放引用对象当然可以减少内存的开销,不用一定要释放



原来还可以不一定要释放 谢谢老张 加分答谢

#14


无论是显式地 Set ... Nothing,还是隐式地通过变量的生命周期自动解除对象引用,都没有直接地“释放”对象,只是减少了对象的引用计数。
在 COM 机制中,只要引用计数归来,就自动释放对象。本来这是为了避免对象多处引用时被提前释放。
但是对象的循环引用恰恰是这种机制的软肋,越复杂的对象模型这个问题越难处理,.Net 框架就完全推翻改成了垃圾回收机制。

#15


明白了。这么说来VB6做的东西里面要是含带复杂的对象模型,那不是问题越多越难处理。
原来.Net是垃圾回收机制。

#16


复杂度其实是看如何设计对象之间的引用关系。
1)比如有两个对象:发票、明细,发票包含一组明细——那么发票肯定需要引用明细(通过集合或数组来包含),但是发票通常作为一个整体处理——明细不需要对发票进行引用;因此没有循环引用的问题。
2)在比如双向链表:很明细前后节点之间有引用,那么释放链表时需要拆开整个链表。
sub FreeDLink(byref pHeader as LinkNode)
    dim pThis as LinkNode, pNext as LinkNode
    set pThis = pHeader
    While Not pThis is nothing
        set pNext = pThis.NextNode
        set pThis.PrevNode = nothing
        set pThis.NextNode = nothing
        set pThis = pNext
    wend
    set pHeader = nothing
end sub


只要记得凡是有循环引用的对象,都需要用特定的方法显式释放就可以了。
一点也不复杂。