2012-04-13 5 views
2

Ich bekomme einen Segmentierungsfehler, wenn ich frei() in der Löschfunktion der folgenden verketteten Liste Implementierung. Bitte sieh es dir an und sag mir, wo ich falsch liege. Wenn ich dieses Programm mit valgrind ausführe, gibt es kein seg. Fehler, es läuft gut. Also kann ich das Problem nicht lösen.Segmentierungsfehler bei 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; 
      } 
    }  
} 

Hier ist ein Teil des Codes aus dem Hauptprogramm:

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 beschwert sich über die malloc und kostenlos für strArray verwendet, aber nicht für die verknüpfte Liste.

+11

Es lohnt sich, ein kurzes (10-20 Zeilen) 'main()' Programm zu zeigen, das zeigt, wie Sie die Liste unter Verwendung der gezeigten Funktionen zuweisen und freigeben. –

+0

Sie sollten strncpy verwenden, um einen Überlauf von node.name zu vermeiden. – ergosys

+0

@ Jonathan Leffler Ich habe den main() Code hinzugefügt, bitte schauen Sie. – ddd

Antwort

2

Führen Sie Ihr Programm durch Valgrind. Freigegebene Segmentierungen sind normalerweise auf Schreibvorgänge außerhalb des zugewiesenen Speichers zurückzuführen (die die Wrapper überschreiben/verfälschen, die das System vor/nach zugeordnetem Speicher platziert). Valgrind ist normalerweise der einfachste Weg herauszufinden, wann die betreffenden Schreibvorgänge passieren.

+0

Ich benutze Valgrind, aber dann läuft das Programm gut. Es gibt kein seg. Fehler passiert und Valgrind scheint keine Speicherfehler anzuzeigen. Der Fehler tritt nur auf, wenn ich das Programm selbst ausführe. – ddd

+0

In diesem Fall muss ich Jonathan Leffler zustimmen: Bitte zeigen Sie uns, wie Sie die Funktionen in Ihrem Code aufrufen. Wenn Sie es nicht versucht haben, führen Sie es durch Valgrind durch, wenn Sie mit Optimierungen kompiliert werden. Speicherfehler werden manchmal nicht angezeigt, bis Sie mit Optimierungen kompilieren. – Leo

+0

Ok, danke Leo. Ich habe den main() Code hinzugefügt, bitte schauen Sie nach. – ddd

5

Druck aus den von malloc() zurück Adressen und auch free() aus dem Wert von temp unmittelbar vor dem Aufruf drucken. Stellen Sie sicher, dass das, was an free() übergeben wird, Ihren Erwartungen entspricht. Wenn Sie einen Zeiger auf free() übergeben, der nicht von malloc() stammt, können Sie auf Probleme stoßen, die Sie sehen.

Es besteht auch die Möglichkeit, dass die Funktion delete_by_id() einen ungültigen Zeiger verwendet. Der Parameter wird dereferenziert, bevor er auf NULL überprüft wird. Ich empfehle, die Funktion in Ihrem Debugger zu durchlaufen und sicherzustellen, dass alle Zeiger so aussehen, wie Sie es erwarten.

2

Ihr Programm Dump Kern Lassen und den Kern in GDB analysieren:

gdb -c yourprog.core yourprog 

dann eine vollständige Backtrace tun:

(gdb) bt full 

Dies wird Ihnen zeigen, wo genau der Grund für Ihre segfault ist und was Werte wurden an die Funktion übergeben.

(bearbeiten) Oh, und kompilieren Sie Ihr Programm mit dem GCC -g Schalter, Debugging-Informationen zu haben.