Fix string memory leaks in Ruby 1.8.6

UPDATE: This is rails-incompatible... which sucks.

Ruby 1.8.6 leaks memory in some surprising places. Even gsub and split on the String class cause some bad headaches. If you're using Haml and 1.8.6 - you are probably in a bit of trouble.
Read more: http://blog.edhickey.com/2008/12/03/memory-leak-in-ruby-186-string-class/

However, simply overwriting the offending methods fixes this memory leak at least. With a weird caveat that you may not use $ variables (eg $1) in any blocks passed to gsub.

Re-read that last sentence... "boom".gsub(/b(.)/) {|m| $1.upcase} will NO LONGER work. Unfortunately... rails uses that syntax, making this blog post probably moot

RUBY:
class ::String
  # This below fixes a bad memory leak in ruby 1.8.6
  # http://blog.edhickey.com/2008/12/03/memory-leak-in-ruby-186-string-class/
  alias :non_garbage_split :split
  alias :non_garbage_gsub :gsub
  alias :non_garbage_gsub! :gsub!
 
  def split(char)
    holder = char
    non_garbage_split(holder)
  end
 
  def gsub(*args, &block)
    if args.size == 1
      non_garbage_gsub(args[0], &block)
    else
      non_garbage_gsub(args[0], args[1], &block)
    end
  end
 
  def gsub!(*args, &block)
    holder = args[0]
    args[0] = holder
    non_garbage_gsub!(*args, &block)
  end
  #end memory leak fixes
end

The Conversation {2 comments}

  1. MarkusQ {Wednesday November 11, 2009 @ 11:01 pm}

    Try something like:

    alias mri_gsub gsub
    def gsub(*args,&block)
    mri_gsub(*args,&block)
    end

    It handles $1 et al fine. Also, you should do the same trick with sub, sub!, etc.

    – MarkusQ

  2. MarkusQ {Thursday November 12, 2009 @ 7:45 pm}

    My bad, I failed to test it thoroughly. It works for special cases, but what is needed is a “works always.”

    – Markus

    P.S. After looking at the C code (and this time testing before I post) I see that File#gets & $_ have the same problem.

Speak Your Peace

  • Comment Policy:Could go here if there's a nagging need Login Instructions: Would go here if there's a desire.