From: Chris Dillon Date: 2011-01-31T03:12:34+09:00 Subject: [ruby-core:34997] [Ruby 1.9-Bug#4346][Open] Sort_by! causes uniq! to crash on array of hashes Bug #4346: Sort_by! causes uniq! to crash on array of hashes http://redmine.ruby-lang.org/issues/show/4346 Author: Chris Dillon Status: Open, Priority: Normal Target version: 1.9.2 ruby -v: ruby 1.9.2p136 (2010-12-25 revision 30365) [x86_64-darwin10.5.0] Summary: Sorting an array of hashes before doing a uniq! causes ruby to crash on uniq!. Program to reproduce: a = [ { :color => "blue", :name => "water" }, { :color => "red", :name => "fire" }, { :color => "white", :name => "wind" }, { :color => "green", :name => "earth" }, { :color => "green", :name => "moss" }, { :color => "white", :name => "snow" } ] a.sort_by! { |e| e[:color] } a.uniq! {|e| e[:color]} puts a A workaround is to do the uniq without the bang. Does not crash. a = a.uniq {|e| e[:color]} Changing the uniq! line as above will not crash and produce the expected result: {:color=>"blue", :name=>"water"} {:color=>"green", :name=>"moss"} {:color=>"red", :name=>"fire"} {:color=>"white", :name=>"wind"} Taking out the sort_by! line also fixes the crashing. Crash Happens on Ruby versions: ruby 1.9.2p136 (2010-12-25 revision 30365) [x86_64-darwin10.5.0] ruby 1.9.2p174 (2011-01-28 revision 30696) [x86_64-darwin10.6.0] ruby 1.9.2p136 (2010-12-25 revision 30365) [x86_64-linux] The method sort_by! is not available in 1.8.7. I did not test with any version of 1.8.7. GDB on Mac yields: (gdb) run Starting program: /Users/user/.rvm/rubies/ruby-1.9.2-head/bin/ruby bug.rb Reading symbols for shared libraries +++... done Reading symbols for shared libraries . done Reading symbols for shared libraries . done Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: KERN_INVALID_ADDRESS at address: 0x000000000000001c rb_ary_decrement_share [inlined] () at /Users/user/.rvm/src/ruby-1.9.2-head/array.c:195 195 long num = ARY_SHARED_NUM(shared) - 1; (gdb) bt #0 rb_ary_decrement_share [inlined] () at /Users/user/.rvm/src/ruby-1.9.2-head/array.c:195 #1 0x000000010000cc99 in rb_ary_modify (ary=4303797720) at array.c:260 #2 0x00000001000128fe in rb_ary_push [inlined] () at /Users/user/.rvm/src/ruby-1.9.2-head/array.c:721 #3 0x00000001000128fe in push_value (key=, val=4303798360, ary=4303797720) at array.c:260 #4 0x0000000100108990 in st_foreach (table=0x1003bb920, func=0x1000128e0 , arg=4303797720) at st.c:778 #5 0x0000000100013573 in rb_ary_uniq_bang (ary=4303797720) at array.c:3435 #6 0x000000010017bc13 in vm_call_cfunc [inlined] () at /Users/user/.rvm/src/ruby-1.9.2-head/vm_insnhelper.c:402 #7 0x000000010017bc13 in vm_call_method (th=0x1003016b0, cfp=0x1004ffef8, num=0, blockptr=0x1004fff21, flag=0, id=, me=0x10033f350, recv=4303797720) at vm_insnhelper.c:260 #8 0x0000000100167dc4 in vm_exec_core (th=0x1003016b0, initial=) at insns.def:1006 #9 0x000000010016fa63 in vm_exec (th=0x1003016b0) at vm.c:1147 #10 0x000000010016fd6b in rb_iseq_eval_main (iseqval=4303800760) at vm.c:1388 #11 0x000000010003f4e2 in ruby_exec_internal (n=0x10086c9b8) at eval.c:214 #12 0x0000000100041e6c in ruby_exec_node [inlined] () at /Users/user/.rvm/src/ruby-1.9.2-head/eval.c:261 #13 0x0000000100041e6c in ruby_run_node (n=) at eval.c:260 #14 0x0000000100000ecf in main (argc=2, argv=0x7fff5fbff368) at main.c:35 GDB on Linux yields: (gdb) run Starting program: /home/user/.rvm/rubies/ruby-1.9.2-p136/bin/ruby bug.rb [Thread debugging using libthread_db enabled] [New Thread 0x7ffff67b5700 (LWP 1423)] Program received signal SIGSEGV, Segmentation fault. rb_ary_decrement_share (ary=6517200) at array.c:195 195 long num = ARY_SHARED_NUM(shared) - 1; (gdb) bt #0 rb_ary_decrement_share (ary=6517200) at array.c:195 #1 rb_ary_modify (ary=6517200) at array.c:260 #2 0x00007ffff79f90a3 in rb_ary_push (ary=6517216, item=7746848) at array.c:721 #3 0x00007ffff79f97ec in push_value (key=, val=7746848, ary=0) at array.c:3399 #4 0x00007ffff7ad4962 in st_foreach (table=0x7634e0, func=0x7ffff79f97e0 , arg=6517200) at st.c:778 #5 0x00007ffff79fdb0c in rb_ary_uniq_bang (ary=6517200) at array.c:3435 #6 0x00007ffff7b35590 in vm_call_cfunc (th=0x603ce0, cfp=0x7ffff68b5f08, num=0, blockptr=, flag=, id=6517336, me=0x6bd020, recv=6517200) at vm_insnhelper.c:402 #7 vm_call_method (th=0x603ce0, cfp=0x7ffff68b5f08, num=0, blockptr=, flag=, id=6517336, me=0x6bd020, recv=6517200) at vm_insnhelper.c:524 #8 0x00007ffff7b285e9 in vm_exec_core (th=0x603ce0, initial=) at insns.def:1006 #9 0x00007ffff7b2edba in vm_exec (th=) at vm.c:1147 #10 0x00007ffff7b2f1f0 in rb_iseq_eval_main (iseqval=6520000) at vm.c:1388 #11 0x00007ffff7a278c2 in ruby_exec_internal (n=) at eval.c:214 #12 0x00007ffff7a278ed in ruby_exec_node (n=0x637cc0) at eval.c:261 #13 0x00007ffff7a2936e in ruby_run_node (n=0x637cc0) at eval.c:254 #14 0x000000000040095b in main (argc=2, argv=0x7fffffffe488) at main.c:35 The crash report (all 1.9's give similar output): /tmp/bug.rb:64: [BUG] Segmentation fault ruby 1.9.2p136 (2010-12-25 revision 30365) [x86_64-darwin10.5.0] -- control frame ---------- c:0004 p:---- s:0010 b:0010 l:000009 d:000009 CFUNC :uniq! c:0003 p:0090 s:0007 b:0007 l:0014e8 d:001a60 EVAL /tmp/bug.rb:64 c:0002 p:---- s:0004 b:0004 l:000003 d:000003 FINISH c:0001 p:0000 s:0002 b:0002 l:0014e8 d:0014e8 TOP --------------------------- -- Ruby level backtrace information ---------------------------------------- /tmp/bug.rb:64:in `
' /tmp/bug.rb:64:in `uniq!' -- C level backtrace information ------------------------------------------- [NOTE] You may have encountered a bug in the Ruby interpreter or extension libraries. Bug reports are welcome. For details: http://www.ruby-lang.org/bugreport.html ---------------------------------------- http://redmine.ruby-lang.org