Project1

标题: 请问Ruby的GC的原理? [打印本页]

作者: taroxd    时间: 2014-5-1 15:38
标题: 请问Ruby的GC的原理?

现在有点搞不懂一个对象什么时候会被回收了,于是写了一点代码。下面是Ruby2.0.0中的运行结果

RUBY 代码复制
  1. def test
  2.   GC.start
  3.   arr = []
  4.   100000.times { a_method(arr) }
  5.   p arr.size
  6. end
  7.  
  8. # test1
  9. def a_method(arr)
  10.   obj = 'temp'
  11.   ObjectSpace.define_finalizer(obj, proc {|id| arr.push(id) })
  12. end
  13. test #=> 0
  14.  
  15. # test2
  16. def a_method(arr)
  17.   ObjectSpace.define_finalizer('temp', proc {|id| arr.push(id) })
  18. end
  19. test #=> 69872


在test1中,虽然‘temp’字符串被赋给了变量obj,但是很快obj就出了作用域无法引用了。这个字符串应该是可以被回收的,可是最后却没有被回收。
在test2中,直接把'temp'作为参数传给了define_finalizer,这样倒是可以触发ruby的垃圾回收机制。

所以到底怎么样的对象可以触发ruby的垃圾回收?我以前一直觉得,当一个对象不被任何东西引用的时候就可以被回收了。但是test1证明似乎不是这样?求科普~~
作者: Sion    时间: 2014-5-1 18:52
本帖最后由 Sion 于 2014-5-1 19:01 编辑

貌似那个 define_finalizer 导致无法回收。
RUBY 代码复制
  1. class T
  2. end
  3.  
  4. def m1
  5.   p a = T.new
  6. end
  7.  
  8. m1
  9. GC.start
  10. ObjectSpace.each_object( T ) {|obj| p obj}
  11. puts '已释放 m1中的 T.new'
  12.  
  13. def m2
  14.   p a = T.new
  15.   ObjectSpace.define_finalizer( a, proc {} )
  16. end
  17.  
  18. m2
  19. GC.start
  20. ObjectSpace.each_object( T ) {|obj| p obj}
  21. puts '无法释放 m2 中的 T.new'

运行环境是 1.9.2
这就是 Ruby 饱受诟病的内存泄露吧。其实都是些鸡肋功能...
作者: masix8    时间: 2014-5-13 22:32
本帖最后由 masix8 于 2014-5-13 22:34 编辑

应该是这样的,定义obj=‘temp’的时候给了一个内存段来存数据,而后面还有使用,这一段是不会当作垃圾的

那个代码里面m2也是,之前定义,后面使用的局部变量不会当作垃圾,全局变量无论何时都不会当作垃圾
作者: 晴兰    时间: 2014-5-14 00:35
提示: 作者被禁止或删除 内容自动屏蔽
作者: 精灵使者    时间: 2014-5-14 08:05
GC只会回收已经不会再引用的东西【也就是断开连接】的东西。
最著名的例子就是
  1. RPG::Cache.clear

  2. Module RPG
  3. Module Cache
  4.   def self.clear
  5. @Cache= {} #清理所有@cache的所有链接
  6.    GC.start #由于失去链接,所有的内存都会被清理
  7.   end
  8. end
  9. end
复制代码

作者: 晴兰    时间: 2014-5-14 21:09
提示: 作者被禁止或删除 内容自动屏蔽
作者: 晴兰    时间: 2014-5-14 23:10
提示: 作者被禁止或删除 内容自动屏蔽




欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1