2011-08-31 10 views
5

Ok, questo è il mio secondo tentativo di eseguire il debug dei problemi di memoria con la mia app Sinatra. Credo di averlo inchiodato in codice di esempio semplice questa volta.Ruby Symbol # to_proc perde riferimenti in 1.9.2-p180?

Sembra che quando si filtra un array attraverso .map(&:some_method), gli elementi di quell'array non vengano recuperati. Eseguire l'equivalente .map{|x| x.some_method} è assolutamente soddisfacente.

Dimostrazione: Dato un semplice classe di esempio:

class C 
    def foo 
    "foo" 
    end 
end 

Se eseguo quanto segue in IRB, questo venga rilevato normalmente:

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 

Quindi esistono più riferimenti a C. Buona. Ma sostituendo map{|x| x.foo} with map(&:foo) (che viene pubblicizzato come equivalente), non ottiene raccolte:

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 > 

Si tratta di un bug rubino? Cercherò in più versioni di ruby ​​per essere sicuro, ma questo sembra un problema ovvio. Qualcuno sa cosa sto sbagliando?

Edit:

ho provato questo in 1.8.7-P352 e non ha il problema. 1.9.3-preview1 fa tuttavia ha ancora il problema. Un bug report è in ordine o sto facendo qualcosa di sbagliato?

Edit2: formattazione (? Perché mettere quattro spazi prima di ogni sintassi di prodotti linea di evidenziazione mentre <pre> tag non lo fanno)

risposta

3

Come a.map(&:foo) dovrebbe essere l'esatto equivalente a a.map{|x| x.foo}, sembra che davvero colpisce un bug in il codice Ruby qui. Non può far male presentare un bug report su (http://redmine.ruby-lang.org/), il peggio che può capitare è che viene ignorato. Puoi diminuirne le possibilità fornendo una patch per il problema.

EDIT: Ho gettato sul mio IRB e ho provato il codice. Posso riprodurre il problema che descrivi su ruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-linux]. Tuttavia, esplicitamente chiamando to_proc sul simbolo non soffre dello stesso problema:

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 

Sembra che siamo di fronte ad un problema con il Symbol -> Proc conversione implicita qui. Forse cercherò di tuffarmi un po 'nella fonte di Ruby più tardi. Se è così, ti terrò aggiornato.

EDIT 2:

soluzione semplice per il problema:

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) {} 

stampe 0.

+0

Proverò a inviare una segnalazione di errore ma sto riscontrando problemi nella configurazione di un account sulla Ruby Redmine. Aspetterò fino a tardi nel caso in cui abbiano problemi con il loro sistema di accesso. –

+0

Sto utilizzando Google Mail e ha contrassegnato la loro e-mail di conferma come spam. Forse dovresti controllare la tua cartella spam: D –

+0

Buona chiamata! Non avevo idea di aver nemmeno inviato una mail di conferma. Comunque, Bug # 5261: http://redmine.ruby-lang.org/issues/5261 –