2017-10-20 31 views
1

GCC ne renvoie aucune erreur ou avertissement. Le programme se sépare après avoir entré un mot de passe de plus de 21 caractères. Au début, j'eu:Signal SIGSEGV reçu: vfprintf.c: Aucun fichier ou répertoire de ce type?

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

obtenir cet avertissement GCC:

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

donc je l'ai changé:

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

parce que la fonction de hachage retourne un entier. strcmp compare deux type const char *.

Lorsque je déboguer le programme en utilisant gdb, il retourne ceci:

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. 

Programme:

#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); 
} 

Note: ce n'est pas un devoir. Je suis juste une personne qui apprend C avec l'aide de personnes qui utilisent Internet.

+1

Il est bon de remarquer que ce n'est pas un devoir, mais il est bon de savoir que nous sommes vraiment heureux de répondre à vos questions ici. Si c'était pour les devoirs, ce serait encore sur le sujet: vous avez un problème clairement énoncé, avec un effort préalable évident, et les gens sont heureux d'aider dans de tels cas. Les questions de devoirs que nous décourageons sont là où il n'y a pas d'effort, ou l'auteur de la question aimerait que quelqu'un les aide à tricher. – halfer

Répondre

2

Dans cette ligne:

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

hash_p n'a jamais été initialisé. Il ne pointe nulle part. Remplacez simplement char *hash_p; par char hash_p[20]. Je ne suis pas sûr de ce que la longueur maximale du hachage est (j'ai supposé 20), alors peut-être 20 devrait être remplacé par une valeur plus appropriée.

0

SuperFastHash() renvoie explicitement un entier non signé de 32 bits (uint32_t). Pourquoi imprimez-vous cela sur une chaîne et comparez/stockez des chaînes?

Il serait plus logique de simplement stocker et comparer les valeurs numériques.


Vous êtes confondre le champ pwd de votre struct:

  • acc[0].pwd stocke un hachage
  • query.pwd stocke le mot de passe en texte clair

Si pour une raison quelconque, vous faire voulez stocker le nombre sous forme de chaîne (peut-être dans un fichier), alors s'il vous plaît faites-le correctement!

Une valeur non signée ne sera jamais négative (votre initialisation de structure indique -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); 

Dans la plupart des cas, vous pourriez sortir avec "%u" comme la chaîne de format, mais "%" PRIu32 est plus sûr/plus correct.


Comme il est indiqué ci-dessous par gcc, l'initialisation de votre struct est incorrect, et travaille actuellement "par erreur".

Vouliez-vous dire ceci:

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

ou ceci:

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

De plus, gcc vous pointer votre erreur si vous compilez avec -Wall (pour activer tous les avertissements) - une très bonne habitude d'entrer dans:

'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))); 
        ^

Enfin, le message vfprintf.c: No such file or directory vous informe que GDB ne peut pas trouver les sources pour printf(), qui dans ce cas est sans rapport avec votre problème.

Si vous utilisez GDB, il est toujours préférable de compiler avec -g pour inclure les informations de débogage dans votre fichier binaire.