2017-10-20 8 views
1

GCC는 오류 또는 경고를 반환하지 않습니다. 암호를 21 자 이상 입력하면 프로그램이 분리됩니다. 는 처음에 나는 있었다 : 신호 SIGSEGV 수신 : vfprintf.c : 해당 파일이나 디렉토리가 없습니까?

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

는 GCC에서이 경고를 얻을 : 해쉬 함수는 int를 반환하기 때문에

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

:

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

그래서 난으로 변경되었습니다. 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;char hash_p[20]으로 바꿉니다. 해시의 최대 길이 (20을 가정)가 어떨지 확실하지 않으므로 20을 적절한 값으로 대체해야합니다.

0

SuperFastHash()은 부호없는 32 비트 정수 (uint32_t)를 명시 적으로 반환합니다. 왜 그것을 문자열로 출력하고 문자열을 비교/저장하고 있습니까?

숫자 값을 저장하고 비교하는 것이 더 합리적입니다. ,

  • acc[0].pwd 저장 해시
  • query.pwd 저장 일반 텍스트 암호

어떤 이유로하는 경우를 :


당신은 현재 구조체의 pwd 필드를 혼동 너 숫자를 문자열로 저장하려고합니다 (아마도 파일에). 그러면 올바르게 입력하십시오!

부호가없는 값은 음수가되지 않습니다 (구조체 초기화는 -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 
,210
$ 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으로 컴파일하여 바이너리에 디버그 정보를 포함시키는 것이 좋습니다.