Problems with String#hash

Dear devs,

I am facing a very NASTY problem with String#hash

Here is the same code that I run on 3 different computers:

root@kosh:~ # irb
irb(main):001:0> "User".hash
=> 690465448
irb(main):002:0> VERSION
=> "1.8.2"

C:\Documents and Settings\drak>irb
irb(main):001:0> "User".hash
=> 690465448
irb(main):002:0> VERSION
=> "1.8.4"

http://tryruby.hobix.com/
Interactive ruby ready.

"User".hash

=> 690465448

VERSION

=> "1.8"

root@victory:~# irb
irb(main):001:0> "User".hash
=> -1457018200
irb(main):002:0> VERSION
=> "1.8.4"

Please nottice that on the last case I get a different result! Any
idea why this happens?

thanks in advance for any help!

George.

···

--
http://blog.gmosx.com

string.c:851
int
rb_str_hash(str)
    VALUE str;
{
    register long len = RSTRING(str)->len;
    register char *p = RSTRING(str)->ptr;
    register int key = 0;

#if defined(HASH_ELFHASH)
    register unsigned int g;

    while (len--) {
  key = (key << 4) + *p++;
  if (g = key & 0xF0000000)
      key ^= g >> 24;
  key &= ~g;
    }
#elif defined(HASH_PERL)
    while (len--) {
  key += *p++;
  key += (key << 10);
  key ^= (key >> 6);
    }
    key += (key << 3);
    key ^= (key >> 11);
    key += (key << 15);
#else
    while (len--) {
  key = key*65599 + *p;
  p++;
    }
    key = key + (key>>5);
#endif
    return key;
}

I suspect those #ifdefs. See your config.h what's compiled in.

···

On 11/24/06, George Moschovitis <george.moschovitis@gmail.com> wrote:

Dear devs,

I am facing a very NASTY problem with String#hash

Here is the same code that I run on 3 different computers:

root@kosh:~ # irb
irb(main):001:0> "User".hash
=> 690465448
irb(main):002:0> VERSION
=> "1.8.2"

C:\Documents and Settings\drak>irb
irb(main):001:0> "User".hash
=> 690465448
irb(main):002:0> VERSION
=> "1.8.4"

http://tryruby.hobix.com/
Interactive ruby ready.
>> "User".hash
=> 690465448
>> VERSION
=> "1.8"

root@victory:~# irb
irb(main):001:0> "User".hash
=> -1457018200
irb(main):002:0> VERSION
=> "1.8.4"

Please nottice that on the last case I get a different result! Any
idea why this happens?

thanks in advance for any help!

George.

darshan@shadow ~ $ ri -T Object#hash
------------------------------------------------------------ Object#hash
     obj.hash => fixnum

···

------------------------------------------------------------------------
     Generates a Fixnum hash value for this object. This function must
     have the property that a.eql?(b) implies a.hash == b.hash. The
     hash value is used by class Hash. Any hash value that exceeds the
     capacity of a Fixnum will be truncated before being used.
darshan@shadow ~ $ ri -T "String#hash"
------------------------------------------------------------ String#hash
     str.hash => fixnum
------------------------------------------------------------------------
     Return a hash based on the string's length and content.

I don't see any reason you should assume the hash to be the same on different machines, or even across different instances of ruby. I'd only assume the hashes of eql? objects to be equal if they are computed within the same run of the script.

Your nasty problem seems to be that you were making an assumption not guaranteed to be true.

What are you actually trying to accomplish? Maybe we can help you find another way.

Darshan

BTW I get the same negative value as you do in your last (4th!) example. Could be a 64-bit thing.

George Moschovitis wrote:

Dear devs,

I am facing a very NASTY problem with String#hash

Here is the same code that I run on 3 different computers:

root@kosh:~ # irb
irb(main):001:0> "User".hash
=> 690465448
irb(main):002:0> VERSION
=> "1.8.2"

C:\Documents and Settings\drak>irb
irb(main):001:0> "User".hash
=> 690465448
irb(main):002:0> VERSION
=> "1.8.4"

http://tryruby.hobix.com/
Interactive ruby ready.

"User".hash

=> 690465448

VERSION

=> "1.8"

root@victory:~# irb
irb(main):001:0> "User".hash
=> -1457018200
irb(main):002:0> VERSION
=> "1.8.4"

Please nottice that on the last case I get a different result! Any
idea why this happens?

thanks in advance for any help!

George.

There is no guarantee that String#hash will behave the same in all versions of Ruby. If this is a problem for you then you probably have an application design problem. Why is this behavior a problem for you?

Kind regards

  robert

···

On 24.11.2006 11:18, George Moschovitis wrote:

Dear devs,

I am facing a very NASTY problem with String#hash

Here is the same code that I run on 3 different computers:

root@kosh:~ # irb
irb(main):001:0> "User".hash
=> 690465448
irb(main):002:0> VERSION
=> "1.8.2"

C:\Documents and Settings\drak>irb
irb(main):001:0> "User".hash
=> 690465448
irb(main):002:0> VERSION
=> "1.8.4"

http://tryruby.hobix.com/
Interactive ruby ready.

"User".hash

=> 690465448

VERSION

=> "1.8"

root@victory:~# irb
irb(main):001:0> "User".hash
=> -1457018200
irb(main):002:0> VERSION
=> "1.8.4"

Please nottice that on the last case I get a different result! Any
idea why this happens?

There is no guarantee that String#hash will behave the same in all
versions of Ruby. If this is a problem for you then you probably have
an application design problem. Why is this behavior a problem for you?

Yeap, this is an application design problem. This is an old (legacy)
application. It is strange that this problem has not shown up all
these years (this is a 4 year old application). And it is really
strange that has gives the exact same result on 4 different ruby
installations and not on the target server.

-g.

···

--
http://blog.gmosx.com

The offending version is the 1.8.4 version that comes with Ubuntu
6.10, has anyone experienced similar problems?

-g.

···

On 11/24/06, Jan Svitok <jan.svitok@gmail.com> wrote:

On 11/24/06, George Moschovitis <george.moschovitis@gmail.com> wrote:
> Dear devs,
>
> I am facing a very NASTY problem with String#hash
>
> Here is the same code that I run on 3 different computers:
>
> root@kosh:~ # irb
> irb(main):001:0> "User".hash
> => 690465448
> irb(main):002:0> VERSION
> => "1.8.2"
>
> C:\Documents and Settings\drak>irb
> irb(main):001:0> "User".hash
> => 690465448
> irb(main):002:0> VERSION
> => "1.8.4"
>
> http://tryruby.hobix.com/
> Interactive ruby ready.
> >> "User".hash
> => 690465448
> >> VERSION
> => "1.8"
>
> root@victory:~# irb
> irb(main):001:0> "User".hash
> => -1457018200
> irb(main):002:0> VERSION
> => "1.8.4"
>
> Please nottice that on the last case I get a different result! Any
> idea why this happens?
>
> thanks in advance for any help!
>
> George.

string.c:851
int
rb_str_hash(str)
    VALUE str;
{
    register long len = RSTRING(str)->len;
    register char *p = RSTRING(str)->ptr;
    register int key = 0;

#if defined(HASH_ELFHASH)
    register unsigned int g;

    while (len--) {
        key = (key << 4) + *p++;
        if (g = key & 0xF0000000)
            key ^= g >> 24;
        key &= ~g;
    }
#elif defined(HASH_PERL)
    while (len--) {
        key += *p++;
        key += (key << 10);
        key ^= (key >> 6);
    }
    key += (key << 3);
    key ^= (key >> 11);
    key += (key << 15);
#else
    while (len--) {
        key = key*65599 + *p;
        p++;
    }
    key = key + (key>>5);
#endif
    return key;
}

I suspect those #ifdefs. See your config.h what's compiled in.

--
http://blog.gmosx.com

BTW I get the same negative value as you do in your last (4th!)
example. Could be a 64-bit thing.

Yeap, that's what I am thinking. The offending machine has an AMD64 processor.

-g.

···

--
http://blog.gmosx.com

The offending version is the 1.8.4 version that comes with Ubuntu
6.10, has anyone experienced similar problems?

It's an x86_64 ?

Guy Decoux