So.

Is it as fun as it used to be?

Ruby’s Array>>shift is shifty

Here is a simple Ruby expression:

	(a = [1, 2, 3]).shift

The value of a will be [2, 3] which is exactly what you’d expect. The thing is, there is a bug here.

The Pick Axe book describes the shift function as:

Returns the first element of arr and removes it (shifting all other elements down by one)

This accurately describes the effect but is a bit misleading. What the implementation actually does (1.8.4) is to increment the C pointer to the first of the array by 1, and return the old value. This difference may be subtle, but it is significant. In particular the 1.8.4 implementation _does not_ overwrite the now inaccessible former first element, there is still a reference to the object and it will not be collected. If that object is big and the array long-lived this might pose a significant memory leak.

Sounds a little unlikely? Well, the Mutex class uses shift to manage the waiting thread list. This means that there are Thread instances in there, and they can be big. This has already created serious problems for Mongrel.

In the near term, you can simply do something like:

	a[0] = nil
	a.shift

A fix would be to modify array.c to look like (please excuse the formatting, sigh):

VALUE
rb_ary_shift(ary)
    VALUE ary;
{
    VALUE top;

    rb_ary_modify_check(ary);
    if (RARRAY(ary)->len == 0) return Qnil;
    top = RARRAY(ary)->ptr[0];
    RARRAY(ary)->ptr[0] = Qnil; /* < <<<ptr++;   /* shift ptr */
    RARRAY(ary)->len--;

    return top;
}

Written by hutch

September 23, 2006 at 6:17 pm

Posted in Ruby

4 Responses

Subscribe to comments with RSS.

  1. Don’t blog about it damnit, write ruby-core@!

    Ryan Davis

    September 23, 2006 at 9:54 pm

  2. I did! I did! Honest! :-)

    Bob Hutchison

    September 25, 2006 at 7:59 am

  3. OT for this post, but I just noticed the attribution line on comments is *really* small. Like, 2px tall on my screen. I’m guessing it’s due to this CSS rule on the cite tag:

    font-size: 0.1em;

    Jacob Fugal

    September 25, 2006 at 10:48 am

  4. You’re right, that is rather small. Is this any better? (it is now xx-small, you might have to force a refresh of the page to see the difference).

    Bob Hutchison

    September 25, 2006 at 12:09 pm


Comments are closed.