0

次のリンク リスト実装の削除関数で free() を実行すると、セグメンテーション違反が発生します。見て、どこが間違っているのか教えてください。このプログラムを valgrind で実行すると、セグメントがありません。エラー、正常に動作します。だから私は問題を理解することができません。

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 について不平を言っていますが、リンクされたリストには不平を言っています。

4

3 に答える 3

6

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

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

于 2012-04-13T21:29:05.790 に答える
5

プログラムにコアをダンプさせ、GDBでコアを分析します。

gdb -c yourprog.core yourprog

次に、完全なバックトレースを実行します。

(gdb) bt full

これにより、セグメンテーション違反の正確な理由と、関数に渡された値がわかります。

(編集)ああ、GCC-gスイッチを使用してプログラムをコンパイルし、デバッグ情報を取得します。

于 2012-04-13T23:08:14.107 に答える
3

valgrind を介してプログラムを実行します。解放時のセグメンテーション違反は、通常、割り当てられたメモリ外への書き込みが原因です (システムが割り当てられたメモリの前後に配置するラッパーを上書き/破損します)。Valgrind は通常、問題の書き込みがいつ発生したかを確認する最も簡単な方法です。

于 2012-04-13T21:22:58.147 に答える