近期开发代码, 出现了一些诡异现象。追查原因是公司使用的签名函数出现的问题。

问题: 代码使用的签名库函数, 对于<=4字节的字符串, 签名就是本身。

 1 #include<stdio.h> 
 2 #include<string.h> 
 3 #include<stdlib.h> 
 4  
 5 int main(){ 
 6     char str[128] = "ni";   //长度是2 
 7     unsigned num[1];    //长度是4 
 8     memset(num, 0, sizeof(unsigned)); 
 9     memcpy(num, str, strlen(str));  //num[0] = 26990 
10      
11     //可以看出, str, num 在前3个字节的内存是相等的 
12     printf("tag = %d\n", memcmp(num, str, strlen(str) + 1));    //把\0也算进去 
13  
14     //对于使用的优化后的签名函数, <= 4个字节则签名为本身(12的签名还是12) 
15     //出现的bug是: 
16     //str:ni, len:3 ---> sign:26990 
17     //num:26990, len:4 ---> sign:26990 
18     return 0;    
19 }

hash函数只是计算签名, 有时会有hash冲突导致实际不相等的字符串, 有相同的hash值。

如果要严格比较, 可以直接比较内存字节。

 1 #include<stdio.h> 
 2 #include<string.h> 
 3 #include<stdlib.h> 
 4  
 5 int is_eq( 
 6         const void* addr1, int len1, 
 7         const void* addr2, int len2){ 
 8     if (len1 != len2){ 
 9         return 1; 
10     }    
11     return memcmp(addr1, addr2, len1) == 0? 0:1; 
12 } 
13  
14 int main(){ 
15     char str[128] = "ni";   //长度是2 
16     unsigned num[1];    //长度是4 
17     num[0] = 26990; 
18      
19     //把字符串的结尾也计算进去 
20     printf("tag = %d\n", is_eq(str, strlen(str) + 1, num, sizeof(num))); 
21     return 0;    
22 }

 

在严格场景下, 可以先用hash做签名, 之后再具体到每个hash值(桶, 拉链)上进行内存字节的比较就可以解决。

评论关闭
IT源码网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!

算法: skiplist 跳跃表代码实现和原理