2016-04-13 7 views
3

私はCを新しくしており、リンクされたリストを手作業で作成しています。今、私はリストの先頭から要素を削除するメソッドに取り組んでいます。それは読み取ります:Cのリンク先一覧:なぜ私はsegfaultingですか?

void remove_from_front(List *l) 
    { 
     Node *head = l->first; 

     l->first = l->first->next; 

     free(head); 
    } 

私は確かにこれは何か明白ですが、私はそれを取得していません。ここに私の質問に関するいくつかの関連データがあります:

先行研究。私はthis oneを含む複数のSOの投稿を見てきましたが、すべては別の実装を使用しています。インターネット上にこのコードの例がありますが、どのように動作するのか分かりませんし、コードが間違っていることを知ることになります。

関連するコードスニペット。

#include <stdio.h> 
#include <stdlib.h> 

typedef struct Node{ 
    void *element; 
    struct Node *next; 
    struct Node *prev; 
} Node; 

typedef struct List{ 
    struct Node *first; 
    struct Node *last; 
} List; 

void add_to_front(List *l, void *toAdd) 
{ 
    Node *n = (Node *)calloc(1, sizeof(Node)); 
    n->element = toAdd; 
    n->next = l->first; 
    n->prev = NULL; 

    if(l->first != NULL) 
    { 
     l->first->prev = n; 
    } 
    l->first = n; 
} 


void add_to_back(List *l, void *toAdd) 
{ 
    Node *n = (Node *)calloc(1, sizeof(Node)); 
    n->element = toAdd; 
    n->next = NULL; 
    n->prev = l->last; 

    if(l->last != NULL) 
    { 
     l->last->next = n; 
    } 
    l->last = n; 
} 

void remove_from_front(List *l) 
{ 
    Node *head = l->first; 

    l->first = l->first->next; 

    free(head); 
} 

int main(int argc, char *argv[]) 
{ 
    List *l = calloc(1, sizeof(List)); 
    l->first = NULL; 
    l->last = NULL; 

    add_to_front(l, (void *)'a'); 
    printf("First element: %c\n", l->first->element); 
    add_to_back(l, (void *)'b'); 
    printf("Last element: %c\n", l->last->element); 
    remove_from_front(l); 
    printf("New first element: %c\n", l->first->element); 
    return 0; 
} 

デバッガ出力:はここに私のプログラム内のコードの残りの部分です。次は、このコードを実行すると得られるデバッガの出力です。

Valgrindは:

==9389== Invalid write of size 4 
==9389== at 0x804852E: remove_from_front (in /home/vagrant/plc/linkedList) 
==9389== by 0x80485D3: main (in /home/vagrant/plc/linkedList) 
==9389== Address 0x8 is not stack'd, malloc'd or (recently) free'd 
==9389== 
==9389== 
==9389== Process terminating with default action of signal 11 (SIGSEGV) 
==9389== Access not within mapped region at address 0x8 
==9389== at 0x804852E: remove_from_front (in /home/vagrant/plc/linkedList) 
==9389== by 0x80485D3: main (in /home/vagrant/plc/linkedList) 
==9389== If you believe this happened as a result of a stack 
==9389== overflow in your program's main thread (unlikely but 
==9389== possible), you can try to increase the size of the 
==9389== main thread stack using the --main-stacksize= flag. 
==9389== The main thread stack size used in this run was 8388608. 
==9389== 

GDB:

Starting program: /home/vagrant/plc/linkedList 
First element: a 
Last element: b 

Program received signal SIGSEGV, Segmentation fault. 
0x0804852e in remove_from_front() 

ノーデバッガで実行可能ファイルを実行し、出力は単純です:

First element: a 
Last element: b 
Segmentation fault 

可能であれば、私は任意の助けをいただければ幸いです。ありがとうございました!

答えて

3

問題は、リスト内の最初の要素の場合は、最後のポインタを設定し、最初の要素も指すようにする必要があります。最初の要素と最後の要素が同じノードを指している必要があります。

// in add_to_front 
if (l->last == NULL) { 
    l->last = l->first; 
} 
// add to back: 
if (l->first == NULL) { 
    l->first = l->last; 
} 
// in remove from front, check if the list is empty: 
if (l->first == NULL) 
    return; 
+0

これは機能しました。どうもありがとうございます。 – Haley

1

第2の問題。最後のノードを削除する場合は、最後の参照をクリアしてください。

void remove_from_front(List *l) 
{ 
    Node *head = l->first; 

    l->first = l->first->next; 

    if (!l->first) 
    { 
    l->last = 0; 
    } 

    free(head); 
} 
+0

それを指摘してくれてありがとう。 if文でnullの代わりにl-> lastをゼロに設定するのはなぜですか? – Haley

+0

ポインタを0またはNULLに設定すると、プレーンCで同じ結果になります。あなたが好きならNULLを使う –

関連する問題