#include <stdio.h>
unsigned int getHashNum(const char *str,unsigned int len,unsigned int maxPrime)
{
register unsigned int sum = 0;
register unsigned int h = 0;
register unsigned short *p = (unsigned short *)str;
register unsigned short *s = (unsigned short *)str;
printf("str:%s,len:%d,h:%d,maxPrime:%d\n",p,len,h,maxPrime);
while(p - s < len)
{
register unsigned short a = *(p++) * (p-s);
printf("a:%d\n",a);
sum += sum ^ a;
h += a;
}
printf("sum:%d\n",sum);
return ((sum << 16) | h) % maxPrime;
}
上面那段代码在主进程和子进程中都调用,传入的参数是一样的,但是返回值不一样,谁能看出来点端倪?
主进程输出:
str:key,len:3,h:0,maxPrime:60
a:0
a:121
a:49900
sum:49934
子进程输出:
str:key,len:3,h:0,maxPrime:60
a:0
a:121
a:29896
sum:29994
我大体找到原因了,问题中的代码是我从网上找到的,确实是为了计算hash值。就像 @米克 说的那样,这里是由于指针出现了越界。函数的入参
const char *str
,在函数内部被转化成了unsigned short *
,即这句代码register unsigned short *p = (unsigned short *)str;
。c语言中char
是一个字节,short是两个字节,指针str
是指向char
的,那么如果执行运算str+1
,得到的结果应该是str的内存地址加一;但是换成表达式p+1
,那么就应该是p的内存地址加二(而不是 @米克 兄说的每次移动4个位置的内存地址距离)。也就是说,在代码中while
循环中,p
的地址每次都是加二的,所以*p
的内容第一次是k
的assic码,第二次是y
的assic码,第三次就越界了,如果是在同一个进程中,多次调用越界得到的内容很有可能是相同的,但是如果换了一个进程,那么越界得到的内容就极有可能是不同的。所以就出现了之前遇到的问题。将while循环稍微修改一下,增加对p内存地址的打印:
主进程中打出来的是这样的:
子进程中打印出来的是这样的:
可以很清晰的看到内存越界,并且
p
指针是每次移动两字节的。解决方法也很简单,将
p
改为使用char
类型指针: