4

この質問からのアイデアは次のとおりです。オブジェクトの作成時に、クラス変数をインクリメントします。オブジェクトが収集されたら、デクリメントします。ご覧のとおり、ファイナライザーが呼び出され、@@no_fooデクリメントされます。しかし、しばらくしてクエリを実行すると、デクリメントはなくなりました。値が上がるだけで、下がることはないようです (2 つのオブジェクトを作成すると、2 と表示されます)。明らかな何かが欠けていますか?

class Foo
  @@no_foo = 0

  def initialize
    puts 'creating object'
    @@no_foo += 1
    ObjectSpace.define_finalizer(self, proc { self.delete })
  end

  def delete
    puts 'deleting object'
    @@no_foo # => 1
    @@no_foo -= 1
    @@no_foo # => 0
  end

  def self.no_foo
    @@no_foo # => 0, 1
  end
end

Foo.no_foo # => 0
f = Foo.new
f = nil

GC.start
Foo.no_foo # => 1

# >> creating object
# >> deleting object
4

2 に答える 2

6

動作しますが、ファイナライズで循環参照があります。ファイナライザーは、収集する必要があるオブジェクトのバインディングに依存します。このソリューションを参照してください。

class Foo
  @@no_foo = 0

  def initialize
    @@no_foo += 1
    ObjectSpace.define_finalizer(self, Foo.method(:delete))
  end

  def self.delete id # also this argument seems to be necessary
    @@no_foo -= 1
  end

  def self.no_foo
    @@no_foo
  end
end

Foo.no_foo # => 0
1000.times{Foo.new}
Foo.no_foo # => 1000

GC.start
Foo.no_foo # => 0
于 2013-05-28T17:25:17.437 に答える