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.

On 11/24/06, George M. [email protected] wrote:

=> “1.8.2”
=> 690465448
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.

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.

On 24.11.2006 11:18, George M. wrote:

=> “1.8.2”
=> 690465448
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?

Kind regards

robert

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.

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

-g.

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.

“G” == George M. [email protected] writes:

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

It’s an x86_64 ?

Guy Decoux