2016-07-07 1 views
2

私はCで純粋に演習としてリンクリストを実装しようとしていました。私のような定義された構造体を持っている:構造体メンバーにアクセスするときのvalgrindによる読み書きエラーが無効です

typedef struct node { 
    int data; 
    struct node* next; 
} 
node; 

typedef struct list { 
    size_t size; 
    node* head; 
} 
list; 

は今、valgrindのは文句の機能は、これらは以下のとおりです。

は(作成)

list* create() { 
    // alocate memory for a new list 
    list* list = malloc(sizeof(list)); 

    if (list != NULL) { 
     list->head = NULL; // this is line 65 
     list->size = 0; 
    } 

    // return pointer to the allocated memory 
    return list; 
} 

(挿入)

void insert(int data, list* list) { 
    if (list == NULL) 
     return; 

    // allocate memory for new node 
    node* newNode = malloc(sizeof(node)); 

    // check if allocation was successful 
    if (newNode == NULL) 
     return; 

    // initialize new node's data 
    newNode->data = data; 

    // make newNode the head of the list 
    newNode->next = list->head; // this is line 88 
    list->head = newNode; 

    // increment size 
    (list->size)++; 
} 

)は(メイン)(

void destroy(list* list) { 
    if (list == NULL) 
     return; 

    node* current = list->head; // this is line 154 
    while (current != NULL) { 
     node* temp = current; 
     current = current->next; 
     free(temp); 
    } 

    free(list); 
} 

を破壊し、次のとおりです。

int main(void) { 
    list* list = create(); 
    insert(1, list); 
    destroy(list); 
    return 0; 
} 

そして、これは何のvalgrindの出力です:

==10601== 1 errors in context 1 of 4: 
==10601== Invalid read of size 8 
==10601== at 0x400A33: destroy (slist.c:154) 
==10601== by 0x400AAE: main (slist.c:167) 
==10601== Address 0x51fc048 is 0 bytes after a block of size 8 alloc'd 
==10601== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==10601== by 0x4007C3: create (slist.c:62) 
==10601== by 0x400A93: main (slist.c:165) 
==10601== 
==10601== 
==10601== 1 errors in context 2 of 4: 
==10601== Invalid write of size 8 
==10601== at 0x400866: insert (slist.c:89) 
==10601== by 0x400AA5: main (slist.c:166) 
==10601== Address 0x51fc048 is 0 bytes after a block of size 8 alloc'd 
==10601== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==10601== by 0x4007C3: create (slist.c:62) 
==10601== by 0x400A93: main (slist.c:165) 
==10601== 
==10601== 
==10601== 1 errors in context 3 of 4: 
==10601== Invalid read of size 8 
==10601== at 0x400852: insert (slist.c:88) 
==10601== by 0x400AA5: main (slist.c:166) 
==10601== Address 0x51fc048 is 0 bytes after a block of size 8 alloc'd 
==10601== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==10601== by 0x4007C3: create (slist.c:62) 
==10601== by 0x400A93: main (slist.c:165) 
==10601== 
==10601== 
==10601== 1 errors in context 4 of 4: 
==10601== Invalid write of size 8 
==10601== at 0x4007DA: create (slist.c:65) 
==10601== by 0x400A93: main (slist.c:165) 
==10601== Address 0x51fc048 is 0 bytes after a block of size 8 alloc'd 
==10601== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==10601== by 0x4007C3: create (slist.c:62) 
==10601== by 0x400A93: main (slist.c:165) 
==10601== 
==10601== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 0 from 0) 

私が正しく出力を理解していた場合は、問題は、メンバー変数のstruct listにアクセスしているようです。しかし、なぜこれらの変数にアクセスするのが問題なのか分かりません。 malloc(sizeof(list))は両方のメンバーに十分なメモリを割り当てる必要があります。問題がどこにあるのでしょうか?

答えて

5
list* list = malloc(sizeof(list)); 

おっと! のlistは、タイプではなく、宣言しているポインタです。だから、あなただけのmalloc - 1つのポインタのための十分なメモリ、あなたが望む構造体ではありません。

変数名で型名をシャドーイングさせないようにしてください。それとも、

list* list = malloc(sizeof(struct list)); 
+0

大漁に動作します。私は、ネーミングがどこかにヒットする知っていました... –

5

を使用しなければならない場合、問題はここにある:

list* list = malloc(sizeof(list)); 

あなたはlistのtypedefとlistという名前の変数を持っています。 sizeof演算子は、型ではなく変数のサイズを使用しています。原則として

は、タイプなどの変数と同じ名前を命名していない:

list* create() { 
    // alocate memory for a new list 
    list* mylist = malloc(sizeof(list)); 

    if (mylist != NULL) { 
     mylist ->head = NULL; 
     mylist ->size = 0; 
    } 

    // return pointer to the allocated memory 
    return mylist ; 
} 
2

問題は別のソリューションを提供@aschepler@dbush

によく識別されますsizeof()を使用する場合は、型のサイズではなく、逆参照される変数のサイズを使用します。

// some_type *ptr = malloc(sizeof (some_type)); 
some_type *ptr = malloc(sizeof *ptr); 

でも影の種類listと変数listで、これは

list* create() { 

    list* list; 

    printf("%zu\n", sizeof(list)); // compiles but the needed code 
    printf("%zu\n", sizeof list); // compiles but the needed code 
    printf("%zu\n", sizeof *list); // good 

    // allocate memory for a new list 
    list = malloc(sizeof *list); 
    ... 

プリント

4 
4 
8 
関連する問題