delphi 为什么BobJenkinsHash函数在这种情况下返回范围错误?

d7v8vwbk  于 2023-10-18  发布在  Jenkins
关注(0)|答案(1)|浏览(171)

在FPC Lazarus下,我使用下面的函数来计算字符串的哈希值,这是用来保存字典中的对象:

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

此函数有时会抛出错误:
项目< Name >引发了异常类“RunError(201)”,消息为:
范围检查错误
在文件< source >第行< Line >:
结果:= BobJenkinsHash(keyStr[1],Length(keyStr)* SizeOf(Char),0);
这在一些用法之后连贯地发生。我不确定是否有一些特定的字符串或使用次数。举例来说:“Button_logo”似乎会引发此错误。
我找不到(不幸的是)相关的文件:我没有发现FPC和 Delphi 文档的文档(因为大多数时间)无关。

iibxawm4

iibxawm41#

我不知道这是否适用于FreePascal,但在 Delphi 中,BobJenkinsHash()函数(顺便说一句,该函数已被弃用)返回一个 * 有符号 * Integer

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

您将返回值赋给 unsignedUInt32。如果函数返回负值(参见Can result of BobJenkinsHash function be negative?),则在启用了范围检查的情况下,您将获得运行时错误。
这个问题同样存在于 Delphi 中的后继函数THashBobJenkins.GetHashValue()中。
因此,您可以:

  1. function MyClass.HashCode(): UInt32;
  2. var
  3. keyStr: string;
  4. begin
  5. keyStr := KeyToString();
  6. {$IFOPT R+} {$RANGECHECKS OFF} {$DEFINE RC_WAS_ON} {$ENDIF}
  7. // or: {$IFOPT R+} {$R-} {$DEFINE RC_WAS_ON} {$ENDIF}
  8. // or: {$PUSH} {$R-} (FPC only)
  9. Result := BobJenkinsHash(PChar(keyStr)^, Length(keyStr) * SizeOf(Char), 0);
  10. {$IFDEF RC_WAS_ON} {$RANGECHECKS ON} {$UNDEF RC_WAS_ON} {$ENDIF}
  11. // or: {$IFDEF RC_WAS_ON} {$R+} {$UNDEF RC_WAS_ON} {$ENDIF}
  12. // or: {$POP} (FPC only)
  13. end;
  • 在将BobJenkinsHash()的返回值赋给UInt32之前,先对它进行类型转换:
  1. function MyClass.HashCode(): UInt32;
  2. var
  3. keyStr: string;
  4. begin
  5. keyStr := KeyToString();
  6. Result := UInt32(BobJenkinsHash(PChar(keyStr)^, Length(keyStr) * SizeOf(Char), 0));
  7. end;
  • HashCode()方法的返回类型更改为Integer
  1. function MyClass.HashCode(): Integer;
  2. var
  3. keyStr: string;
  4. begin
  5. keyStr := KeyToString();
  6. Result := BobJenkinsHash(PChar(keyStr)^, Length(keyStr) * SizeOf(Char), 0);
  7. end;
展开查看全部

相关问题