2015-07-07 2 views
0

Я начал изучать программирование C несколько дней назад в книге «Программирование на C», и у меня есть предварительное знание Java. Вставка узла в связанный список очень легко в Java, но я подумал, что если я мог бы сделать то же самое в С. Итак, я придумал эту программу,Ошибка сегментации при попытке вставить узел в связанный список

#include "node.h" 

void insertEntry(struct node* root, struct node* after) 
{ 
    struct node* first = root; 
    while(first != (struct node*) 0) 
    { 
     if(first->value == after->value) 
     { 
      struct node ins; 
      ins.value = 3456; 
      ins.next = first->next; 
      first->next = &ins; 
     } 
     first = first->next; 
    } 
} 

int main(void) 
{ 
    struct node n1, n2, n3; 
    struct node* list_pointer = &n1; 

    n1.value = 100; 
    n1.next = &n2; 

    n2.value = 200; 
    n2.next = &n3; 

    n3.value = 300; 
    n3.next = (struct node*) 0; 

    void insertEntry(struct node* root, struct node* after); 

    while (list_pointer != (struct node*) 0) 
    { 
     printf("%i\n", list_pointer->value); 
     list_pointer = list_pointer->next; 
    } 
    printf("\n"); 

    list_pointer = &n1; 

    insertEntry(list_pointer, &n2); 

    while (list_pointer != (struct node*) 0) 
    { 
     printf("%i\n", list_pointer->value); 
     list_pointer = list_pointer->next; 
    } 

    return 0; 
} 

node.h

#include <stdio.h> 

struct node 
{ 
    int value; 
    struct node* next; 
}; 

В основном, эта программа принимает указатель на первый элемент связанного списка и указатель на элемент, после которого он должен быть вставлен, и вставляет новый узел после этого узла.

Но когда я запускаю это, моя программа падает, и я не могу найти, где и почему эта ошибка возникает. Я просмотрел код в java и попытался реализовать его в C.

Спасибо.

+0

Вы использовали отладчик как 'gdb' найти именно там, где происходит ошибка сегментации? –

ответ

4

Вот ваша проблема:

{ 
     struct node ins; // You create an object in the stack 
     ins.value = 3456; 
     ins.next = first->next; 
     first->next = &ins; // You reference your object 
    } // Your object is popped out of the stack and ceases to exist 
    // Any access to first->next past this block may cause segfault 

Для того, чтобы избежать этого, вы можете создать ins с malloc(), но будьте осторожны: это не Java, и вы должны отслеживать все объекты, которые вы выделенных в куче сам.

0

Вы должны прочитать на gdb и как его использовать.

gcc -Wall -O0 -g x.c -o x 

x быть вашей программой для компиляции с отладочной информацией и без оптимизации.

затем запустите свою программу через gdb, чтобы найти местоположение/возникновение неисправности. т.е.

gdb x 
+2

Это может быть комментарий не ответ – LPs

+0

@LPs Мне не разрешено оставлять комментарии. Недостаточно репутации. – J2R5M3

+0

По крайней мере, не на пост О.П. – J2R5M3

3

Основная проблема заключается в установке узла, который выделяется в стеке - это недопустимый как только функция остается. Чтобы выделить новую память, вам нужно malloc() (не забудьте сделать free(), когда закончите, нет мусора).

Несколько боковые примечания:

  • Это совершенно бессмысленно бросать 0, когда используется в качестве указателя на любой конкретный тип указателя ... 0 0.

  • Вам не нужен корневой узел для вставки, так зачем его передавать первым?

  • Объявление прототипа внутри функции (в этом случае: main) не имеет особого смысла ... оно будет работать без того, что функция, которую вы хотите вызвать, уже определена в том же файле.

  • #include заголовки, где они нужны! node.h не требуется stdio, основная программа.

Вариант примерно вашей программы, которая будет работать:

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

struct node 
{ 
    int value; 
    struct node *next; 
}; 

struct node *insertEntry(struct node* after, int val) 
{ 
    assert(after); /* not NULL */ 

    struct node *new = malloc(sizeof(struct node)); 
    new->value = val; 
    new->next = after->next; 
    after->next = new; 
    return new; 
} 

void freeNodeList(struct node* root) 
{ 
    struct node *current, *last; 

    current = root; 

    while (current) 
    { 
     last = current; 
     current = current->next; 
     free(last); 
    } 
} 

int main(void) 
{ 
    struct node *n1, *n2, *n3; 
    struct node *ptr; 

    n1 = malloc(sizeof(struct node)); 
    n2 = malloc(sizeof(struct node)); 
    n3 = malloc(sizeof(struct node)); 

    n1->value = 100; 
    n1->next = n2; 

    n2->value = 200; 
    n2->next = n3; 

    n3->value = 300; 
    n3->next = 0; 

    insertEntry(n2, 250); 

    ptr = n1; 
    while (ptr) 
    { 
     printf("%d\n", ptr->value); 
     ptr = ptr->next; 
    } 

    freeNodeList(n1); 
    return 0; 
} 
+0

Фактически, 'ins' станет недействительным, как только вы покинете блок' if'. Как только переменная выходит за пределы области видимости, компилятор может повторно использовать память, даже если она выполняет ту же функцию. –

Смежные вопросы