加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby – 在创建第二个对象之前未调用Finalizer,除非使用weakref

发布时间:2020-12-17 02:33:22 所属栏目:百科 来源:网络整理
导读:我正在玩 ruby终结器,并注意到一些对我来说很奇怪的行为.我可以将触发代码减少到以下内容: require "weakref"class Foo def initialize ObjectSpace.define_finalizer(self,self.class.finalize) end def self.finalize proc { puts "finalizing" } endendF
我正在玩 ruby终结器,并注意到一些对我来说很奇怪的行为.我可以将触发代码减少到以下内容:

require "weakref"

class Foo
    def initialize
        ObjectSpace.define_finalizer(self,self.class.finalize)
    end

    def self.finalize
        proc {
            puts "finalizing"
        }
    end
end

Foo.new # does not work
#WeakRef.new(foo) # Using this instead,everything works as expected
sleep 1
ObjectSpace.garbage_collect
puts "... this did not finalize the object"

Foo.new
ObjectSpace.garbage_collect
puts "but this did?"

正如程序所说,在第二次调用Foo.new之前没有运行终结器.我尝试在第一次调用垃圾收集器之前添加更多延迟(虽然据我所知,它根本不是必需的)但是这没有做任何事情.

奇怪的是,如果我使用注释掉的行i,第一个终结器会被调用,就像我期望的那样.在程序退出之前仍未调用第二个.

任何人都可以解释为什么会这样吗?我正在使用ruby 1.9.3p194(2012-04-20修订版35410)[x86_64-linux]运行Ubuntu 12.10.我尝试读取weakref代码,但据我所知,它所做的只是存储对象object_id以便以后检索它.

编辑:
?我知道在这种情况下手动调用垃圾收集器是没有意义的.我只是想了解这背后的机制.

解决方法

您无法收集您的Foo参考,因为它在您的终结器中被引用!因此,因为终结器本身持有对象的引用,所以GC从不收集它,因此从不触发终结器.您只需使用WeakRef作为终结器本身就可以解决这个问题:

require "weakref"

class Foo
  class << self
    attr_accessor :objects_finalized

    def finalize
      proc {
        @objects_finalized ||= 0
        @objects_finalized += 1
      }
    end
  end

  def initialize
    ObjectSpace.define_finalizer WeakRef.new(self),self.class.finalize
  end
end

describe Foo do
  it "should be collected" do
    Foo.new
    expect { GC.start }.to change {
      ObjectSpace.each_object(Foo){} }.from(1).to(0)
  end

  it "should be finalized when it is collected" do
    expect { begin; Foo.new; end; GC.start }.to change {
      Foo.objects_finalized }.from(nil).to(1)
  end
end

结果如下:

% rspec weakref.rb
..

Finished in 0.03322 seconds
2 examples,0 failures

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读