2012-04-13 15 views
2

次のリンクリスト実装の削除機能でfree()を実行すると、セグメンテーション違反が発生します。私が間違っているところを見て、私に教えてください。 valgrindでこのプログラムを実行すると、segはありません。失敗、それは正常に動作します。だから私は問題を理解することができません。ここで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; 
      } 
    }  
} 

は、メインプログラムからのコードの一部です:

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のはStrArrayとのためではなく、リンクリストに使用するmallocとfree文句を言っています。

+11

表示されている関数を使ってリストをどのように割り当て、解放するのかを示す 'main()'短い(10行の)プログラムを表示する価値があります。 –

+0

node.nameのオーバーランを避けるには、strncpyを使用する必要があります。 – ergosys

+0

@Jonathan Leffler main()コードを追加しました。どうぞご覧ください。 – ddd

答えて

2

valgrindを使用してプログラムを実行します。 Segfaultsは通常、割り当てられたメモリの外側(システムが割り当てられたメモリの前後に配置するラッパーを上書き/破損する)以外の書き込みが原因です。 Valgrindは通常、問題の書き込みがいつ発生するかを知る最も簡単な方法です。

+0

私はvalgrindを使用しましたが、プログラムは正常に動作します。セグはありません。エラーが発生し、valgrind doesntはメモリエラーを指摘しているようです。この障害は、プログラムを単独で実行した場合にのみ発生します。 – ddd

+0

その場合、私はJonathan Lefflerに同意する必要があります。コード内の関数の呼び出し方法を教えてください。試していない場合は、最適化してコンパイルしたときにvalgrindを実行してください。最適化でコンパイルするまで、メモリエラーは表示されません。 – Leo

+0

よろしくお願いします。 main()コードを追加しました。どうぞご覧ください。 – ddd

5

malloc()によって返されたアドレスを出力し、free()の呼び出しの直前にtempの値を出力します。 free()に渡される内容が、期待どおりのものと一致することを確認してください。何とかmalloc()から来ていないfree()へのポインタを渡していると、あなたが見ているような問題が発生する可能性があります。

機能delete_by_id()が無効なポインタを使用している可能性もあります。 pパラメータは、NULLがチェックされる前に参照解除されます。私はあなたのデバッガの関数を歩き、すべてのポインタが見えるように見えることを確認することをお勧めします。

2

プログラムダンプコアをしようとGDBでコアを分析:

gdb -c yourprog.core yourprog 

その後、フルバックトレースを実行します。あなたのセグメンテーション違反のため、正確な理由があると何どこ

(gdb) bt full 

これはあなたが表示されます値が関数に渡されました。

(編集)ああ、GCC -gスイッチでプログラムをコンパイルして、デバッグ情報を取得してください。

関連する問題