delphilazarus

Why BobJenkinsHash function returns range error in this case?


Under FPC Lazarus, I am using the following function to compute the hash of a string, this is used to save the object in a dictionary:

function MyClass.HashCode(): UInt32;
var
  keyStr: string;
begin
  keyStr := KeyToString();
  Result := BobJenkinsHash(keyStr[1], Length(keyStr) * SizeOf(Char), 0);
end;

This function sometimes throws an error:

Project < Name > raised exception class ' RunError(201)' with message:
Range check error

in file < source > at line < Line >:
Result := BobJenkinsHash(keyStr[1], Length(keyStr) * SizeOf(Char), 0);

This happens coherently after some usages. I am not sure if some specific strings or number of usages. For example: "Button_logo" seems to raise this error.

I could not find (unfortunately) relevant documentation about this: I found no documentation for FPC and Delphi documentation is (as most of the time) irrelevant.


Solution

  • I don't know if this applies to FreePascal, but in Delphi the BobJenkinsHash() function (which is deprecated1, BTW) returns a signed Integer:

    function BobJenkinsHash(const Data; Len, InitData: Integer): Integer;
                                                                 ^^^^^^^
    

    You are assigning that return value to an unsigned UInt32. If the function returns a negative value (see Can result of BobJenkinsHash function be negative?), you will get a runtime error if you have Range Checking enabled.

    1 this same issue exists for the function's successor in Delphi, THashBobJenkins.GetHashValue(), too.

    So, you can either: