ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 Excel Home精品图文教程库
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
300集Office 2010微视频教程 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 6194|回复: 17

[求助] 一个对象会多次分配内存吗?

[复制链接]

TA的精华主题

TA的得分主题

发表于 2014-7-17 13:06 | 显示全部楼层 |阅读模式
本帖已被收录到知识树中,索引项:数据类型和基本语句
for i=1 to n
  set aa=CreatObject(.....)   '可能是任意需要的对象
  .......
  .......
next

求问:我应该把Set aa= Nothing放在循环外还是循环内更好?换句话说,aa会被分配n个内存地址还是1个内存地址?

TA的精华主题

TA的得分主题

发表于 2014-7-17 13:26 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
放外面,set语句的效率比较低,放里面会影响速度的。

至于你问的问题,里外都一样,vb会自动释放没有引用的内存

TA的精华主题

TA的得分主题

发表于 2014-7-17 13:29 | 显示全部楼层
循环里的set aa=CreatObject(.....)   始终只会产生一个对象aa,占用1个内存块
所以循环内不需要set aa=nothing

TA的精华主题

TA的得分主题

发表于 2014-7-17 13:54 | 显示全部楼层
本帖最后由 hehex 于 2014-7-17 14:01 编辑

这个问题很有趣。

aa 是一个局部变量,里面装的是对象实体的引用。在你执行set aa = createobject("...") 之前,aa 里面的内容是null, 当你执行该语句的时候,该语句在堆(heap) 中开辟一块内存,生成对象实体,然后将对象实体的引用值赋给变量aa, 比如说是该实体的首地址作为一个指针,通常来说我们在VB 里面不叫指针,而是叫对象的引用。

不管叫什么了,我们都可以通过aa 来访问到这个对象的实体。

当一次循环结束,进入下一次循环的时候,再次执行 set aa = createobject("...") 的时候,这时候 aa 里面的内容是上一次循环时堆内存中那个对象实体的引用,现在呢,首先在堆内存里另外建一个对象实体,然后将这个新的内存对象的实体的引用赋给aa。那么原来的堆内存里有的那个对象实体还存在吗?当然存在,只不过无法再访问到了,这是失去引用的堆内存对象实体。简称为内存垃圾,如果内存垃圾不能被自动回收,则该程序在结束前这块内存永远无法再被使用,产生的这种问题学名叫做内存泄漏。

这里,我和学导老师的看法有分歧,VB6(vba 取自vb6)  的内存管理机制是无法自动释放这样失去引用的对象实体的,即无法自动实现垃圾回收,这点与C ,C++ 完全一致。(高版本的vb 的内存管理机制不同,比如vb.net 就可以自动回收这些失去引用的内存了)

再说一下set aa = nothing 语句,set aa = nothing 语句从字面上看是断开aa 与它的实体之间的引用关系,即将aa 的内容恢复为null, 实则不然,这句话是有操作内存的作用的。除断开引用外,还会清除该对象在堆内存中的实体,这就是学导老师提到的降低效率的原因,因为释放内存也是耗费系统资源的。因此个人意见可以把set aa=Nothing 和C++ 的delete 语句,c 的 free 语句联系起来,都是干一样的活。

最后说一下放循环内还是外的问题,关键看你的对象实体有多大,一般情况下不必那么严谨。但是也有意外,我曾经碰到一个极端的求助例子。某网抓程序,网页对象,抓下来一个大概3M ,然后上千页循环读取,没有在循环内set aa = nothing 来释放内存,最后内存泄漏到系统崩溃了。

但是通常情况下,举个例子,一个字典或者几个字典循环嵌套都没有占多大的内存,现在计算机的内存空间足够大,随便折腾,就不值得在循环内一一 set xx = Nothing 来释放了,正如学导老师所言,严重影响执行效率。

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-7-17 14:16 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
楼上的都是高手!特别感谢hehex老师讲了这么大一段!

TA的精华主题

TA的得分主题

发表于 2014-7-17 14:50 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助

.net的内存回收机制是一大特色,讲.net都会讲它的内存管理和垃圾回收机制。对于VB在何时回收内存,这个真不清楚,估计会在很晚进行,因此个人觉得对象的创建和消除应尽可能的显式处理,不要过分依赖系统的自动处理,哪怕在.net环境中。

对于类似楼主的在循环体内创建对象的方法,我觉得一般情况下应避免。

TA的精华主题

TA的得分主题

发表于 2014-7-17 15:06 | 显示全部楼层
hehex 发表于 2014-7-17 13:54
这个问题很有趣。

aa 是一个局部变量,里面装的是对象实体的引用。在你执行set aa = createobject("..." ...

我用objptr函数测试对象接口指针,加了set nothing时,每次都相同
不加set nothing,循环时第1、3、5.。。次为同一地址,2、4、6。。。为同一地址

也就是说可以使用原来的内存?

TA的精华主题

TA的得分主题

发表于 2014-7-17 15:30 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖最后由 hehex 于 2014-7-17 15:31 编辑
sz_wap 发表于 2014-7-17 15:06
我用objptr函数测试对象接口指针,加了set nothing时,每次都相同
不加set nothing,循环时第1、3、5.。 ...

加了set nothing 之后每次都相同可以理解,因为set nothing 有释放堆内存的功能。然后下次开辟堆内存的时候继续使用原位置。没加1,3,5 相同 现象说明set aa = createobject("new object") 之后,将失去引用的部分内存释放了。即set 语句是先开内存,后释放掉原内存。所以才是1,3,5 一样,2,4,6 一样。有可能是Set 语句做了优化。

这么看来学导老师说的VB 内存管理方式是正确的,VB 通过Set 语句变相实现了内存管理。

可是,我明明碰到过上面的例子啊,循环中不停开对象导致内存泄漏的例子。 我需要再去查查相关资料。

TA的精华主题

TA的得分主题

发表于 2014-7-17 23:58 | 显示全部楼层
一个例子,不知是否能说明问题

类模块
  1. Private Sub Class_Initialize()
  2.     MsgBox "创建新实例"
  3. End Sub

  4. Private Sub Class_Terminate()
  5.     MsgBox "销毁对象"
  6. End Sub
复制代码
测试模块
  1. Private Sub testClass()
  2.     Dim a As clsTsst
  3.    
  4.     Set a = New clsTsst
  5.     Set a = New clsTsst '执行第二次创建对象时,会调用第一个对象的析构函数
  6.    
  7. End Sub
复制代码

TA的精华主题

TA的得分主题

发表于 2014-7-18 08:46 | 显示全部楼层
hehex 发表于 2014-7-17 15:30
加了set nothing 之后每次都相同可以理解,因为set nothing 有释放堆内存的功能。然后下次开辟堆内存的时 ...

如果用WB控件的话,会有内存泄漏问题,这不一定是控件的bug。

如果采用动态创建WB的方法,据说可以手工释放内存

其实VB内存泄漏的原因有很多,对函数内的数组的不恰当操作、使用了有Bug的控件、对象间的相互引用、使用了某些API而没有调用对应的释放函数等等

您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

关闭

最新热点上一条 /1 下一条

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-4-24 05:23 , Processed in 0.036623 second(s), 10 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表