2017-10-20 102 views
1

GCC不返回任何错误或警告。输入密码超过21个字符后,程序会发生段错误。 起初我:接收到SIGSEGV信号:vfprintf.c:没有这样的文件或目录?

hash_p = SuperFastHash(query.pwd, strlen(query.pwd)); 

从GCC得到这样的警告:

warning: assignment makes pointer from integer without a cast [-Wint- conversion] 
hash_p = SuperFastHash(query.pwd, strlen(query.pwd)); 
     ^

,所以我把它改为:

sprintf(hash_p, "%d", SuperFastHash(query.pwd, strlen(query.pwd))); 

因为哈希函数返回一个int。 strcmp比较两个类型的const char *。

当调试用gdb程序,它返回:

Program received signal SIGSEGV, Segmentation fault. 
0xb7e500d5 in _IO_vfprintf_internal (s=<optimized out>, format=<optimized out>, 
ap=0xbffff46c "\261\[email protected]") at vfprintf.c:1636 
1636 vfprintf.c: No such file or directory. 

计划:

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <netdb.h> 
#include <stdarg.h> 
#include <stdint.h> 

#define BUF_SIZE 1024 
#undef get16bits 
#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ 
    || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) 
#define get16bits(d) (*((const uint16_t *) (d))) 
#endif 

#if !defined (get16bits) 
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\ 
        +(uint32_t)(((const uint8_t *)(d))[0])) 
#endif 

uint32_t SuperFastHash (const char * data, int len) { 
uint32_t hash = len, tmp; 
int rem; 

    if (len <= 0 || data == NULL) return 0; 

    rem = len & 3; 
    len >>= 2; 

    for (;len > 0; len--) { 
     hash += get16bits (data); 
     tmp = (get16bits (data+2) << 11)^hash; 
     hash = (hash << 16)^tmp; 
     data += 2*sizeof (uint16_t); 
     hash += hash >> 11; 
    } 

    switch (rem) { 
     case 3: hash += get16bits (data); 
       hash ^= hash << 16; 
       hash ^= ((signed char)data[sizeof (uint16_t)]) << 18; 
       hash += hash >> 11; 
       break; 
     case 2: hash += get16bits (data); 
       hash ^= hash << 11; 
       hash += hash >> 17; 
       break; 
     case 1: hash += (signed char)*data; 
       hash ^= hash << 10; 
       hash += hash >> 1; 
    } 

    hash ^= hash << 3; 
    hash += hash >> 5; 
    hash ^= hash << 4; 
    hash += hash >> 17; 
    hash ^= hash << 25; 
    hash += hash >> 6; 

    return hash; 
} 


struct log_n { 
     char uid[BUF_SIZE]; 
     char pwd[BUF_SIZE]; 
}; 

struct log_n acc[1] = { 
     "username","-1257730142" 
}; 

struct log_n query; 

int main() { 

    char *hash_p;  

    do { 
      do{ 
        printf("Username: "); 
        fgets(query.uid, sizeof query.uid, stdin); 
        query.uid[strcspn(query.uid, "\n")] = '\0'; 
        if (strlen(query.uid) < 4) { 
          printf("Username must be between four and eight characters.\nTry again.\n"); 
        } 
        if (strlen(query.uid) > 8) { 
          printf("Username must be less than eight characters.\nTry again.\n"); 
        } 
      } while (strlen(query.uid) < 4 || strlen(query.uid) > 8); 

      do{ 
        printf("Password: "); 
        fgets(query.pwd, sizeof query.pwd, stdin); 
        query.pwd[strcspn(query.pwd, "\n")] = '\0'; 
        sprintf(hash_p, "%d", SuperFastHash(query.pwd, strlen(query.pwd))); 

        if (strlen(query.pwd) < 21) { 
          printf("Password must be atleast twenty-one characters long.\nTry again.\n"); 
        } 
      } while (strlen(query.pwd) < 21); 
    } while (strcmp(query.uid, acc->uid) !=0 || strcmp(hash_p, acc->pwd) !=0); 
} 

注:这不是一个家庭作业。我只是在使用互联网的人的帮助下学习C的人。

+1

这可以说这不是一项家庭作业,但值得一提的是我们真的很欢迎这里的作业问题。如果这是作业,它仍然是话题:你有一个明确表示的问题,事先做出明显的努力,人们很乐意在这种情况下提供帮助。我们劝阻的作业问题是没有努力的地方,或者问题作者希望有人帮助他们作弊。 – halfer

回答

2

在这一行:

sprintf(hash_p, "%d", SuperFastHash(query.pwd, strlen(query.pwd))); 

hash_p从未初始化。它没有任何意义。

只需用char hash_p[20]代替char *hash_p;即可。我不确定散列的最大长度是多少(我假设为20),所以20应该替换为更合适的值。

0

SuperFastHash()明确返回一个无符号的32位整数(uint32_t)。你为什么将它打印到字符串并比较/存储字符串?

只是存储和比较数值会更有意义。


您正在混淆你的结构的pwd领域:

  • acc[0].pwd存储哈希
  • query.pwd存储明文密码

如果由于某种原因,你想要将数字存储为字符串(可能位于文件中),请正确使用它!

an unsigned值永远不会为负数(您的结构初始化指定-1257730142)。

char input_pwd[] = "my password"; 
uint32_t input_hash; 
char hash_str[11]; /* 32-bit unsigned int can't be more than 10 characters, +1 for nul */ 

input_hash = SuperFastHash(input_pwd, strlen(input_pwd)); 
snprintf(hash_str, sizeof(hash_str), "%" PRIu32, input_hash); 

在大多数情况下,你可以逃脱"%u"作为格式字符串,但"%" PRIu32更安全/更正确。


如低于gcc指出,你的结构初始化是不正确的,目前作品“错误”。

你的意思是这样的:

struct log_n acc[1] = { 
     { "username", "3037237154" } 
}; 

或本:

struct log_n acc = { 
     "username", "3037237154" 
}; 

此外,gcc将指向你在你的错误,如果你有-Wall(启用所有警告)编译 - 一个非常好的习惯:

'hash_p' is used uninitialized in this function 
$ gcc main.c -o main -Wall 
main.c:72:23: warning: missing braces around initializer [-Wmissing-braces] 
struct log_n acc[1] = { 
        ^
main.c:72:23: note: (near initialization for 'acc') 
main.c: In function 'main': 
main.c:99:21: warning: 'hash_p' is used uninitialized in this function [-Wuninitialized] 
        sprintf(hash_p, "%d", SuperFastHash(query.pwd, strlen(query.pwd))); 
        ^

最后,vfprintf.c: No such file or directory消息通知您GDB无法找到来源printf(),在这种情况下是不相关的,您的问题。

如果您打算使用GDB,那么使用-g进行编译以在您的二进制文件中包含调试信息总是一个好主意。

相关问题