2011-08-31 43 views
5

好吧,這是我第二次嘗試用我的Sinatra應用程序調試內存問題。我相信我這次已經將它簡化爲簡單的示例代碼。Ruby符號#to_proc泄漏1.9.2-p180中的引用?

看來,當我通過.map(&:some_method)篩選數組時,它會導致該數組中的項不會被垃圾收集。運行等效的.map{|x| x.some_method}是完全正常的。

演示:給定一個簡單的示例類:

class C 
    def foo 
    "foo" 
    end 
end 

如果我在運行IRB以下時,它會收集正常:

ruby-1.9.2-p180 :001 > a = 10.times.map{C.new} 
=> [...] 
ruby-1.9.2-p180 :002 > b = a.map{|x| x.foo} 
=> ["foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo"] 
ruby-1.9.2-p180 :003 > ObjectSpace.each_object(C){} 
=> 10 
ruby-1.9.2-p180 :004 > a = nil 
=> nil 
ruby-1.9.2-p180 :005 > b = nil 
=> nil 
ruby-1.9.2-p180 :006 > GC.start 
=> nil 
ruby-1.9.2-p180 :007 > ObjectSpace.each_object(C){} 
=> 0 

所以到C的引用不復存在。好。但用map{|x| x.foo} with map(&:foo)(這是標榜當量),它不會收集:

ruby-1.9.2-p180 :001 > a = 10.times.map{C.new} 
=> [...] 
ruby-1.9.2-p180 :002 > b = a.map(&:foo) 
=> ["foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo"] 
ruby-1.9.2-p180 :003 > ObjectSpace.each_object(C){} 
=> 10 
ruby-1.9.2-p180 :004 > a = nil 
=> nil 
ruby-1.9.2-p180 :005 > b = nil 
=> nil 
ruby-1.9.2-p180 :006 > GC.start 
=> nil 
ruby-1.9.2-p180 :007 > ObjectSpace.each_object(C){} 
=> 10 
ruby-1.9.2-p180 :008 > 

這是一個Ruby的錯誤?我會嘗試在更多版本的紅寶石確定,但這似乎是一個明顯的問題。任何人都知道我在做什麼錯了?

編輯:

我已經在1.8.7-P352嘗試這樣做,它不會有問題。 1.9.3-preview1 確實但是仍然存在問題。是錯誤報告按順序還是我做錯了什麼?

EDIT2:格式化(?爲什麼把四個空格每一行產生語法高亮之前,而<pre>標籤不)

回答

3

由於a.map(&:foo)應該是完全等效於a.map{|x| x.foo},好像你真的遇到一個錯誤Ruby代碼在這裏。在(http://redmine.ruby-lang.org/)上提交錯誤報告並不會造成什麼影響,可能發生的最壞情況是被忽略。您可以通過爲問題提供補丁來降低這種可能性。

編輯:我扔我的IRB,並嘗試你的代碼。我可以重現你在ruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-linux]上描述的問題。然而,明確地對符號調用to_proc不會有同樣的問題:

irb(main):001:0> class C; def foo; end; end 
=> nil 
irb(main):002:0> a = 10.times.map { C.new } 
=> [...] 
irb(main):004:0> b = a.map(&:foo.to_proc) 
=> [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil] 
irb(main):005:0> ObjectSpace.each_object(C){} 
=> 10 
irb(main):006:0> a = b = nil 
=> nil 
irb(main):007:0> GC.start 
=> nil 
irb(main):008:0> ObjectSpace.each_object(C){} 
=> 0 

看來,我們所面臨的問題與隱Symbol -> Proc轉換這裏。也許我會稍後嘗試着深入一些Ruby源代碼。如果是這樣,我會保持更新。

編輯2:

的問題簡單解決方法:

class Symbol 
    def to_proc 
    lambda { |x| x.send(self) } 
    end 
end 

class C 
    def foo; "foo"; end 
end 

a = 10.times.map { C.new } 
b = a.map(&:foo) 
p b 
a = b = nil 
GC.start 
p ObjectSpace.each_object(C) {} 

打印0

+0

我會嘗試發送一個錯誤報告,但我無法在Ruby redmine上設置一個帳戶。如果他們的登錄系統出現問題,我會等到晚些時候。 –

+0

我正在使用Google Mail,並將其確認郵件標記爲垃圾郵件。也許你應該檢查你的垃圾郵件文件夾:D –

+0

良好的通話!我不知道他們甚至發送了確認郵件。無論如何,Bug#5261:http://redmine.ruby-lang.org/issues/5261 –