2017-10-20 18 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は2つの型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)を明示的に返します。なぜそれを文字列に出力し、文字列を比較/格納するのですか?

数値を保存して比較するのが理にかなっています。


あなたは現在、あなたの構造体のpwd分野混乱している:何らかの理由で

  • acc[0].pwd店舗ハッシュ
  • query.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" } 
}; 

またはこの:

あなたはこのもしかしてあなたは(すべての警告を有効にする)-Wallでコンパイルする場合

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

をさらに、gccはあなたのミスであなたを指しています - に入るための非常に良い習慣:

'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をコンパイルしてバイナリにデバッグ情報を含めることをお勧めします。

関連する問題