2012-04-13 12 views
2

Je reçois une erreur de segmentation lorsque je fais free() dans la fonction delete de l'implémentation de la liste chaînée suivante. S'il vous plaît jeter un oeil et dites-moi où je me trompe. Quand je lance ce programme avec valgrind, il n'y a pas de seg. faute, ça fonctionne bien. Donc, je ne suis pas capable de comprendre le problème.Segmentation fault at free()

typedef struct node { 
    char name[100]; 
    int id; 
    struct node* next; 
} Node; 

void insert(Node** p, char* _name, int _id) 
{ 
    Node *temp, *prev; 
    temp = malloc(sizeof(struct node)); 
    temp->next = NULL; 
    strcpy(temp->name,_name); 
    temp->id = _id; 

    if(*p == NULL) { 
      *p = temp; 
    } 
    else { 
      for(prev = *p; prev->next!=NULL; prev=prev->next); 
      prev->next=temp; 
    } 
} 

/* Delete entry 
    @params p first element 
     _id  ID to delete 
*/ 
void delete_by_id(Node** p, int _id) { 
    Node *temp, *prev; 
    prev = NULL; 
    for(temp = *p; temp!= NULL; prev = temp, temp=temp->next) { 
      if(temp->id == _id) { 
       printf("Deleting entry with id: %d\n", temp->id); 
       if(prev == NULL) 
        *p = temp->next; 
       else 
        prev->next= temp->next; 
       free(temp); 
       return; 
      } 
    }  
} 

Voici une partie du code du programme principal:

Node* p; 
int main() { 
     ... 
     ... 
     buf[rval]=0; 
     char* tokens = strtok(buf, "+"); 
     char* strArray[5]; /* up-to 5 words can be stored */ 
     int n = 0; 
     while (tokens) 
     { 
     strArray[n] = malloc(strlen(tokens) + 1); 
     strcpy(strArray[n++], tokens); 
     tokens = strtok(NULL, "+"); 
     } 
     int type = 0; 
     if(strcmp(strArray[0], "1") == 0) 
      type = 1; 
     else 
      type = 2; 
     char* name = ""; 
     if(type == 1) { 
      name = strArray[1]; 
      insert(&p, name, clients[i]); 
      display(&p); 
     } else { 
      name = strArray[1]; 
      rval = search(&p, name); 
      if(rval) { 
       delete_by_id(&p, rval); 
       display(&p); 
      } 
     } 

     for (i = 0; i < 5; i++) 
     { 
     if (strArray[i]) // check for null data 
      free(strArray[i]); 
     } 
     ... 
     ... 
} 

int search(Node** p, char* _name) { 
    Node *temp; 
    for (temp = *p; temp!= NULL; temp = temp->next) { 
      if (strcmp((char *)temp->name, _name)==0) { 
        printf("Name matched: %s\n", temp->name); 
        return temp->id; 
      } 
    } 
    return 0; 
} 

Valgrind se plaint du malloc et libre utilisé pour strArray mais pas pour la liste chaînée.

+11

Il serait utile de montrer un programme court (10-20 lignes) 'main()' qui montre comment vous allouez et libérez la liste en utilisant les fonctions montrées. –

+0

Vous devriez utiliser strncpy pour éviter de dépasser node.name. – ergosys

+0

@Jonathan Leffler J'ai ajouté le code principal(), s'il vous plaît jeter un oeil. – ddd

Répondre

2

Exécutez votre programme via valgrind. Segfaults on free est généralement dû à des écritures en dehors de la mémoire allouée (qui écrase/corrompt les wrappers que le système place avant/après la mémoire allouée). Valgrind est généralement le moyen le plus simple de savoir quand les écritures en question se produisent.

+0

J'ai utilisé valgrind, mais le programme fonctionne correctement. Il n'y a pas de seg. faute de passe et valgrind ne semble pas signaler les erreurs de mémoire. La faute se produit seulement quand je cours le programme par lui-même. – ddd

+0

Dans ce cas, je suis d'accord avec Jonathan Leffler: S'il vous plaît montrez-nous comment vous appelez les fonctions dans votre code. Si vous ne l'avez pas essayé, lancez-le dans valgrind lorsqu'il est compilé avec des optimisations. Les erreurs de mémoire ne s'affichent parfois que lorsque vous compilez avec des optimisations. – Leo

+0

Ok, merci Leo. J'ai ajouté le code principal(), s'il vous plaît jeter un oeil. – ddd

5

Imprimez les adresses renvoyées par malloc() et imprimez également la valeur temp immédiatement avant l'appel au free(). Assurez-vous que ce qui est passé à free() correspond à ce que vous attendiez. Si d'une façon ou d'une autre vous passez un pointeur vers free() qui ne vient pas de malloc(), vous pouvez rencontrer des problèmes comme vous le voyez.

Il est également possible que la fonction delete_by_id() utilise un pointeur non valide. Le paramètre p est déréférencé avant d'être vérifié pour NULL. Je vous recommande de parcourir la fonction dans votre débogueur et de vous assurer que tous les pointeurs ressemblent à ce que vous attendez d'eux.

2

Laissez votre coeur de vidage de programme et d'analyser le noyau dans GDB:

gdb -c yourprog.core yourprog 

puis faire une rétrospection complète:

(gdb) bt full 

Cela va vous montrer où exactement la raison de votre segfault et ce les valeurs ont été transmises à la fonction. (0)

(edit) Oh, et compilez votre programme avec le commutateur GCC -g pour avoir des informations de débogage.