C# 反向工程String.GetHashCode
GetHashCode的行为取决于程序体系结构。因此,它将在x86中返回一个值,在x64中返回一个值。我有一个必须在x86中运行的测试应用程序,它必须预测必须在x64上运行的应用程序的哈希代码输出 下面是mscorwks中String.GetHashCode实现的反汇编C# 反向工程String.GetHashCode,c#,gethashcode,C#,Gethashcode,GetHashCode的行为取决于程序体系结构。因此,它将在x86中返回一个值,在x64中返回一个值。我有一个必须在x86中运行的测试应用程序,它必须预测必须在x64上运行的应用程序的哈希代码输出 下面是mscorwks中String.GetHashCode实现的反汇编 public override unsafe int GetHashCode() { fixed (char* text1 = ((char*) this)) { char* ch
public override unsafe int GetHashCode()
{
fixed (char* text1 = ((char*) this))
{
char* chPtr1 = text1;
int num1 = 0x15051505;
int num2 = num1;
int* numPtr1 = (int*) chPtr1;
for (int num3 = this.Length; num3 > 0; num3 -= 4)
{
num1 = (((num1 << 5) + num1) + (num1 >≫ 0x1b)) ^ numPtr1[0];
if (num3 <= 2)
{
break;
}
num2 = (((num2 << 5) + num2) + (num2 >> 0x1b)) ^ numPtr1[1];
numPtr1 += 2;
}
return (num1 + (num2 * 0x5d588b65));
}
}
public覆盖不安全的int-GetHashCode()
{
已修复(char*text1=((char*)this))
{
char*chPtr1=text1;
int num1=0x15051505;
int num2=num1;
int*numPtr1=(int*)chPtr1;
对于(int num3=此长度;num3>0;num3-=4)
{
num1=((num1≫ 0x1b))^numPtr1[0];
如果(num3 0x1b))^numPtr1[1];
numPtr1+=2;
}
返回值(num1+(num2*0x5d588b65));
}
}
任何人都可以将此函数移植到安全的实现中吗?哈希代码不能跨平台重复,甚至不能在同一系统上多次运行同一程序你走错了路。如果你不改变方向,你的人生道路将很艰难,总有一天会以眼泪告终。
你想解决的真正问题是什么?您是否可以编写自己的哈希函数,或者作为扩展方法,或者作为包装类的
GetHashCode
实现,并改用该类?首先,Jon是正确的;这是愚蠢的差事。我们用来“吃我们自己的狗粮”的框架的内部调试构建每天都会更改哈希算法,以防止人们构建依赖于不可靠的实现细节的系统,甚至是测试系统,这些细节在任何时候都会被记录为可能发生更改
我的建议是退后一步,问问自己为什么要尝试做这样危险的事情,而不是将一个被证明不适合仿真的系统的仿真纳入其中。这真的是一个要求吗
其次,StackOverflow是一个技术问答网站,而不是一个“免费为我做我的工作”的网站。如果你下定决心要做这件危险的事情,并且你需要一个能将不安全代码重写成同等安全代码的人,那么我建议你雇用一个能为你做到这一点的人 虽然这里给出的所有警告都是有效的,但它们不能回答问题。我遇到过这样一种情况:GetHashCode()不幸地已经被用于生产中的持久值,我别无选择,只能使用默认的.NET 2.0 32位x86(little endian)算法重新实现。我在没有不安全的情况下重新编码,如下所示,这似乎是可行的。希望这对别人有帮助
// The GetStringHashCode() extension method is equivalent to the Microsoft .NET Framework 2.0
// String.GetHashCode() method executed on 32 bit systems.
public static int GetStringHashCode(this string value)
{
int hash1 = (5381 << 16) + 5381;
int hash2 = hash1;
int len = value.Length;
int intval;
int c0, c1;
int i = 0;
while (len > 0)
{
c0 = (int)value[i];
c1 = (int)value[i + 1];
intval = c0 | (c1 << 16);
hash1 = ((hash1 << 5) + hash1 + (hash1 >> 27)) ^ intval;
if (len <= 2)
{
break;
}
i += 2;
c0 = (int)value[i];
c1 = len > 3 ? (int)value[i + 1] : 0;
intval = c0 | (c1 << 16);
hash2 = ((hash2 << 5) + hash2 + (hash2 >> 27)) ^ intval;
len -= 4;
i += 2;
}
return hash1 + (hash2 * 1566083941);
}
//GetStringHashCode()扩展方法相当于Microsoft.NET Framework 2.0
//在32位系统上执行的String.GetHashCode()方法。
公共静态int GetStringHashCode(此字符串值)
{
int hash1=(5381 0)
{
c0=(int)值[i];
c1=(int)值[i+1];
intval=c0 |(c127))^intval;
如果(len3?(int)值[i+1]:0;
intval=c0 |(c127))^intval;
len-=4;
i+=2;
}
返回hash1+(hash2*1566083941);
}
以下内容准确地再现了.NET 4.7(可能更早)上的版本。这是由以下公式给出的哈希代码:
字符串
实例的默认值:“abc”.GetHashCode()
StringComparer.Ordinal.GetHashCode(“abc”)
- 采用
StringComparison.Ordinal
枚举的各种String
方法
System.Globalization.CompareInfo.GetStringComparer(CompareOptions.Ordinal)
通过对发布版本进行全面的JIT优化测试,这些版本的性能略优于内置的.NET代码,并且已经过大量的单元测试,以确保与.NET
行为完全等效。请注意,x86和x64有不同的版本。你的计划通常应该包括这两个方面;在相应的代码清单下面是一个调用工具,它在运行时选择适当的版本
x86-(.NET以32位模式运行)
static unsafe int GetHashCode_x86_NET(int* p, int c)
{
int h1, h2 = h1 = 0x15051505;
while (c > 2)
{
h1 = ((h1 << 5) + h1 + (h1 >> 27)) ^ *p++;
h2 = ((h2 << 5) + h2 + (h2 >> 27)) ^ *p++;
c -= 4;
}
if (c > 0)
h1 = ((h1 << 5) + h1 + (h1 >> 27)) ^ *p++;
return h1 + (h2 * 0x5d588b65);
}
static unsafe int GetHashCode_x64_NET(Char* p)
{
int h1, h2 = h1 = 5381;
while (*p != 0)
{
h1 = ((h1 << 5) + h1) ^ *p++;
if (*p == 0)
break;
h2 = ((h2 << 5) + h2) ^ *p++;
}
return h1 + (h2 * 0x5d588b65);
}
readonly static int _hash_sz = IntPtr.Size == 4 ? 0x2d2816fe : 0x162a16fe;
public static unsafe int GetStringHashCode(this String s)
{
/// Note: x64 string hash ignores remainder after embedded '\0'char (unlike x86)
if (s.Length == 0 || (IntPtr.Size == 8 && s[0] == '\0'))
return _hash_sz;
fixed (char* p = s)
return IntPtr.Size == 4 ?
GetHashCode_x86_NET((int*)p, s.Length) :
GetHashCode_x64_NET(p);
}
您可以使用索引器访问字符串中的字符。为什么需要哈希代码匹配?不要出于任何目的存储哈希代码,因为实现可以随时更改。向下滚动至“规则:GetHashCode的使用者不能依赖它随时间或跨appdomains保持稳定”。还有“安全问题:不要使用GetHashCode”一节“标签外”也看到了我没有意识到GetHashCode是如此柔韧。所以,是的,傻瓜们的差事。我同意。很好的建议。我将继续使用一种可重复的、与体系结构无关的散列算法。Kenn:作为将来的参考,您可能会感兴趣。当你可以只看实际的、完全注释的源代码时,为什么要反汇编.NETFramework代码呢?天哪!Eric,你真的很生气:)我没意识到gethashcode是如此柔韧。所以,是的,傻瓜们的差事。我同意。很好的建议。我将继续使用可重复的、与体系结构无关的哈希算法。@Konstantin:我一点也不生气;作为我的客户,我希望Kenn成功。因此,我在声明中坚定地认为:(1)这是一个坏主意,可能会导致未来的高成本;(2)StackOverflow是一个询问事实的好地方,也是一个要求免费工作的坏地方。知道这一点的人更有可能成功地使用StackOverflow。@配置器:我不清楚。算法每天都在变化,因为算法的内部版本考虑到了当前版本号,而当前版本号每天都在变化。读取String.cs的文本让我笑了<代码>/。。。这些都是代码中的错误\n hash1^=thissembly.DailyBuildNumber代码>只能以眼泪结束@巴卡尔: