那些情况下可能会发生内存泄漏?现在用VB写了一个控件,调用了另外两个COM对象,一个是VC写的,一个是VB写的,测试发现有内存泄漏,短时间看不出来有MEMLEAK,用自动测试7个小时才发现很明显的MEMLEAK。

解决方案 »

  1.   

    主要精力放到VC写的那个COM对象上看看。VB使用的是安全数组,一般不会发生泄漏。
      

  2.   

    领导说vc那个组件应该没有问题,因为那个是老外写的,用了很久了,也比较庞大,控件是我们这边写的,所以怀疑VB写的那部分代码。难道VB使用NEW来产生一个对象,没有SET NOTHING 也不会产生泄漏吗?
      

  3.   

    VB写的代码也很奇怪,以前用过引用和CreateObject来使用COM对象,他这里是用的API,
    Dim hr As Long
        Dim rclsid As GUID
        Dim riid As GUID
        Dim Context As Long
        Dim ServerInfo As COSERVERINFO
        Dim AuthInfo As COAUTHINFO
        Dim mqi As MULTI_QI
        Dim radServer As RSRadMgr.Automation
        Dim almObject As Object    Dim className As String
        Dim desStr As String    rclsid.Data1 = &H111DF4A2
        rclsid.Data2 = &H68F0
        rclsid.Data3 = &H11D2
        rclsid.Data4(0) = &H94
        rclsid.Data4(1) = &HFA
        rclsid.Data4(2) = &H0
        rclsid.Data4(3) = &HC0
        rclsid.Data4(4) = &H4F
        rclsid.Data4(5) = &H8E
        rclsid.Data4(6) = &HD4
        rclsid.Data4(7) = &HA1    riid.Data1 = &H111DF4A1
        riid.Data2 = &H68F0
        riid.Data3 = &H11D2
        riid.Data4(0) = &H94
        riid.Data4(1) = &HFA
        riid.Data4(2) = &H0
        riid.Data4(3) = &HC0
        riid.Data4(4) = &H4F
        riid.Data4(5) = &H8E
        riid.Data4(6) = &HD4
        riid.Data4(7) = &HA1    mqi.hr = 0
        Set mqi.pItf = Nothing
        mqi.pIID = VarPtr(riid)    AuthInfo.dwAuthnSvc = RPC_C_AUTHN.RPC_C_AUTHN_WINNT
        AuthInfo.dwAuthzSvc = RPC_C_AUTHZ.RPC_C_AUTHZ_NONE
        AuthInfo.pwszServerPrincName = vbNullString
        AuthInfo.dwAuthnLevel = RPC_C_AUTHN_LEVEL.RPC_C_AUTHN_LEVEL_NONE
        AuthInfo.dwImpersonationLevel = RPC_C_IMP_LEVEL.RPC_C_IMP_LEVEL_IMPERSONATE
        AuthInfo.pAuthIdentityData = vbNullString
        AuthInfo.dwCapabilities = RPC_C_QOS.RPC_C_QOS_CAPABILITIES_DEFAULT    ServerInfo.dwReserved1 = 0&
        ServerInfo.dwReserved2 = 0&
        ServerInfo.pAuthInfo = VarPtr(AuthInfo)
        ServerInfo.pwszName = StrPtr(sServerName)
        Context = CLSCTX_SERVER    ' Create an instance of the Load Manager
        hr = CoCreateInstanceEx(rclsid, CLng(0), Context, ServerInfo, CLng(1), mqi)If hr < 0 Or mqi.hr < 0 Then
            desStr = "Could not start load manager" 'LoadResString(IDS_CouldNotStartLoadManager)
            hr = vbObjectError + 2 ' Set a user defined error code
            Err.Raise Number:=hr, Description:=desStr
            Exit Function
        End If    Set radServer = mqi.pItf
        If radServer Is Nothing Then
            desStr = "Set Load Manager Failed" 'LoadResString(IDS_SetLoadManagerFailed)
            desStr = desStr & Hex(Err.Number)
            hr = vbObjectError + 2 ' Set a user defined error code
            Err.Raise Number:=hr, Description:=desStr
            Exit Function
        End If
                                            '{2E53D61F-D836-11D0-BEE4-080009B3AC18}
        Set almObject = radServer.StartServer("{E17C000C-204E-11D4-AB9A-00C04F9915E3}", hr)
        If hr < 0 Then
            desStr = "Create RAD Server Failed" 'LoadResString(IDS_CreateObjectExFailed)
            desStr = desStr & Hex(hr)
            hr = vbObjectError + 3 ' Set a user defined error code
            Err.Raise Number:=hr, Description:=desStr
            Exit Function
        End If    Set GetAlmServer = almObject
        If GetAlmServer Is Nothing Then
            desStr = "Create GetAlmServer Failed" 'LoadResString(IDS_GetSpcServerSetFailed)
            desStr = desStr & Hex(Err.Number)
            hr = vbObjectError + 4 ' Set a user defined error code
            Err.Raise Number:=hr, Description:=desStr
            Exit Function
        End If
      

  4.   

    正看<高级visual basic编程>,头疼中……书上讲了不少关于数组和内存的问题,可以参考。
      

  5.   

    子程序中使用了集合,使用了Set colTagNames = New Collection,最后没有Set colTagNames = Nothing,这样会不会内存泄漏
      

  6.   

    vc那边的看过了,发现了一个bstr没有free,还有vb代码中的所有该set nothing的东西都设置了,ADO也从2。1改为了2。8,因为ADO2。6之前的有内存泄漏问题,改过后测试了一个晚上,内存还是会泄漏,最后达到接近400m,把机器给跑死了。只有一个地方我怀疑,那个vb组件中有一个event传过来一个recordset,在控件中这个事件处理程序中把这个recordset赋值给一个ado控件(Set Adodc1.Recordset = rsvDlgData),最后也没有把rsvDlgData关掉,也没有set nothing,这样会不会产生memleak啊,测试一测就是几个小时,所以先问问大家了
      

  7.   

    vb没有自动管理内存,需要我们去注意,所以使用时要注意Set OBJ= Nothing 是否每个使用的都有,捕捉错误的时候是否加入了这些。切忌
      

  8.   

    1、一个vc写的log server组件,是用mfc写的com进程外服务器,不停的写log文件,
    2、一个是vb写的com进程内组件ExtractData,通过他向log server请求log数据,并且将请求得到的数据以事件的方式通知控件LogViewer,
    3、控件LogViewer也是vb写得控件,上面有一个datagrid和adodc控件,
    4、通过vb那个组件ExtractData的函数HistSvrCallback_NewHistoricalData(这是log server接收到数据的通知函数)中将数据处理后加入到一个recordset中,然后通过它触发的事件来通知控件,将这个纪录集传给adodc控件的recordset,然后在datagrid里面显示log数据。
    5、当我在一个程序中打开一个使用这个控件来显示数据的窗口,等数据取到后,然后关闭窗口,然后再打开,重复这样的过程,大约4个小时候(大约1000次这样的关闭窗口),程序使用内存会从17,344k增到29,792k,如果让他这样测试10个小时的话,使用的内存会长到300多m,我512m的机器,整个程序会死掉。
      

  9.   

    bounds checker我用了,看不到问题,bounds checker对vb没有什么作用吧。关键是这个控件是vb做的,ExtractData组件也是vb写的,我看了很久,没有发现什么问题,google搜到很多的信息,ado2.6之前得recordset对象会发生内存泄漏,不过我的ado用的是2.8,还看到一个recordset绑定到textbox也会发生内存泄漏问题,公司以前有过类似的问题,问同事,他说这是ado自己的问题,因为取数据耗时过长和数据量过大,这样重复的打开关闭这个窗口,使得内存没有完全释放,这样累积使得最终虚拟内存不足,不知道是不是这方面的原因。
      

  10.   

    一般单用VB写的代码不会有内存泄漏。最多也就是没有得到及时的释放而已。VB使用引用计数器检测对象的生命期,当所有的引用版本全部销毁后,对象自动释放。因此VB代码本身很难写出内存泄漏的代码。但是引用过其他部件就很难讲了,而且很难调试。说了一大通废话,只想说:看看VC的组件,和ADO。
      

  11.   

    我可以百分之百的确性:VB代码有可能存在内存泄露。如果你不回收,系统不可能为你回收。
    很多类提供了释放内存的方法,如果在调用他们之前就Set为Nothing,就会产生一个内存泄露。
    如果把对象放在一个集合中,然后直接将这个集合Set为Nothing,也很可能产生内存泄露。应该调用所有对象的释放方法——如果存在的话,再将对象Set为Nothing,然后再将集合中的对象一一Remove,最后再将集合Set为Nothing
      

  12.   

    我同意小陆的说法。在vb中使用com/com+或其它只要是关于对像的类型时,使用之后必须亲自放到。否则vb不会放掉。最好用对象自写的销毁方法,再set nothing.
      

  13.   

    所以还是COM组件那边的问题。因为组件内部额外申请的资源不被VB管理。同月月鸟所说,先调用组件的释放函数,然后再销毁引用。VB应该能够保证:在一个对象的所有引用都被释放后,对象被释放。但是VB无法保证这种释放是完全的。