gpt4 book ai didi

Ruby Symbol#to_proc 在 1.9.2-p180 中泄漏引用?

转载 作者:数据小太阳 更新时间:2023-10-29 07:18:00 25 4
gpt4 key购买 nike

好的,这是我第二次尝试调试 Sinatra 应用程序的内存问题。我相信这次我已经将它确定为简单的示例代码。

似乎当我通过 .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 错误吗?我会尝试使用更多版本的 ruby​​ 来确定,但这似乎是一个明显的问题。有人知道我做错了什么吗?

编辑:

我已经在 1.8.7-p352 中试过了,没有问题。 1.9.3-preview1 确实但是仍然有问题。是按顺序提交错误报告还是我做错了什么?

Edit2:格式化(为什么在每行前放置四个空格会产生语法高亮,而 <pre> 标签却不会?)

最佳答案

因为 a.map(&:foo) 应该完全等同于 a.map{|x| x.foo},看来你真的遇到了 Ruby 代码中的一个错误。在 (http://redmine.ruby-lang.org/) 上提交错误报告并没有坏处,最坏的情况是它被忽略了。您可以通过为该问题提供补丁来降低出现这种情况的可能性。

编辑: 我启动了 IRB 并尝试了您的代码。我可以在 ruby 1.9.2p290(2011-07-09 修订版 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

关于Ruby Symbol#to_proc 在 1.9.2-p180 中泄漏引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7263268/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com