2015-09-30 5 views
0

Я продолжаю получать Segmentation Fault (core dumped) ошибки времени выполнения, и я не могу понять, почему.C Сбой сегментации (сбрасываемый сердечник) Связанный список

Мой код:

struct Node 
{ 
    void *next; 
    void *val; 
}; 
typedef struct Node* NodePtr; 

struct List 
{ 
    NodePtr head; 
}; 
typedef struct List* ListPtr; 

ListPtr create() 
{ 
    ListPtr ptr = malloc(sizeof(struct List)); 

    return ptr; 
} 

int insert(ListPtr list, void *obj) 
{ 
    NodePtr newObj = malloc(sizeof(struct Node)); 

    //Cast next as a self referencing Node 
    newObj->next = (NodePtr) newObj->next; 

    //Point to beginning of list 
    NodePtr current = list->head; 

    if(list->head == NULL) 
    { 
     newObj->val = obj; 
     list->head->next = newObj; 
     newObj->next = NULL; 

     return 1; 
    } 

    return 0; 
} 

int main(int argc, char *argv[]) 
{ 
    int x = 2; 
    int *p = &x; 

    ListPtr thing = create(); 

    insert(thing, p); 

    return 0; 
} 

Ошибка здесь: list->head->next = newObj после некоторой отладки. Я думал, что мне пришлось выделить память для списка -> head -> next, но когда я добавил код для этого, он все равно дал мне ту же ошибку. Исправляю ли я неправильно или не правильно распределяю память? Любая помощь будет оценена, спасибо!

+1

'list-> head-> следующая = newObj;' если (list-> голова == NULL) ==> 'нуль- > next = newObj; '. также 'list-> head' не инициализируется. – BLUEPIXY

+1

Pro-tip: в ваш первый год (ы) C, не используйте typedef. Это только смутило бы вас. – wildplasser

+0

Спасибо, я забыл инициализировать голову. Добавил это, но все равно не повезло. Я также должен использовать typedef, у него есть typedef. Мой код, который я написал, не является частью этого, но он похож. –

ответ

1

Просто положите это вместе, отлично работает.

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


struct Node { 
     void *next; 
     void *val; 
}; 
typedef struct Node* NodePtr; 

struct List { 
    NodePtr head; 
}; 
typedef struct List* ListPtr; 

ListPtr CreateList() { 
    ListPtr ptr = malloc(sizeof(struct List)); 
    return ptr; 
} 

void Insert(ListPtr list, void *obj) { 
     // create and initialize new node 
    NodePtr newObj = malloc(sizeof(struct Node)); 
    newObj->val = obj; 
    newObj->next = NULL; 

    //Point to beginning of list 
    NodePtr curr = list->head; 
    // Add node to the list 
    if(curr == NULL) // if no head node, make newObj the head node 
    { 
     list->head = newObj; 
    } 
    else{ // otherwise traverse the list until you find the last node (the one that points to a null as the next) 
     while(1) { 
       if(curr->next != NULL) { 
         curr = curr -> next; 
       } else { 
         curr->next = newObj; 
       } 
       list->head = newObj; 
       newObj->val = obj; 
       list->head->next = newObj; 
       newObj->next = NULL; 
     } 
    } 
} 
int main() { 
    int x = 2; 
    int *p = &x; 

    ListPtr thing = CreateList(); 

    Insert(thing, p); 

    return 0; 
} 
+1

Как и выше, я получаю ту же ошибку. –

+0

Спасибо, это сработало, и я, наконец, понимаю всех остальных. –

1

Вы проверяете, является ли list->head NULL, а затем выполните некоторые операции с этим. Измените это на if(list->head != NULL) { ... }

+0

Я все еще получаю ту же ошибку, если я ее сменил на '! ='. –

1

При мысли, malloc не гарантирует, что выделенная память пуста. Хорошая практика - установить все значения, которые имеют значение после выделения. list-> head, вероятно, не является нулевым

также: новыйObj-> следующий = (NodePtr) новыйObj-> следующий; не установлен на рациональное значение, он устанавливает, какая память была установлена ​​- планировали ли вы newObj-> next = (NodePtr) newObj; ?

list-> head не должен ссылаться, если null. list-> head-> next будет действителен только в том случае, если он не равен нулю.

, если вы на самом деле хотите, чтобы создать список,

newObj->val = obj; 
if (list->head == NULL) { newObj->next = list->head; } 
list->head = newObj; 

что либо или двигаться вниз list-> шейной> следующая цепь до следующего имеет нулевое значение, и установить, что быть newObj-> рядом. Если это так, то это, возможно, хорошая идея, newObj-> next должен быть установлен как NULL, а не сам.

Можете ли вы понять, как будет выглядеть ваш список - это круговой? он растет из головы (list-> head) или хвост (последний -> следующий)? Вы заметили хвост, когда listObject-> next == NULL или когда listObject-> next == listObject?

+0

Вы говорите, что я должен использовать 'memset()' после 'mallo()'? , когда вы создаете односвязный список, у вас есть собственный референтный узел. Например, 'public class Node {Node link; int value;}'. Вот почему я сделал 'newObj-> next = (NodePtr) newObj- > next'. Я хотел, чтобы рядом был реляционный, как на Java, и вы правы, я пытался сделать list-> head-> next == NULL. Как бы я сделал его как референтный, как в Java? –

+1

memset работает. На большинстве платформ NULL = 0 (это тоже получается, но обычно это не очень важно). Self-reference is newObj-> next = newObj; Но почему я сам ссылаюсь? Означает ли это для (listIter = list-> head; listiter! = Listiter-> next; listiter = listiter-> next) - стиль итерации, который вы хотите? (где listiter является NodePtr) –

+0

Для самостоятельной ссылки я имею в виду, что я хочу, чтобы 'void * next' был' NodePtr next'. Однако я не могу написать это в структуре узла, поэтому я попытался сделать это снаружи. –

1

Я понимаю, что этот ответ в основном стилистичен. Но я считаю, что (плохой) стиль и (плохие) привычки являются (важной) частью (плохого) программирования. Подводя итоги ...


  • (в большинстве случаев) определения типов не требуется; они просто вводят псевдоним для того, что уже существует.
  • [правило семи] человеческих читателей имеет ограниченное количество идентификаторов («имен»), которые они могут отслеживать. Это может быть 7. Сведение к минимуму количества отдельных слов облегчает чтение.
  • также, читатель должен помнить, что xPtr и XNode являются связаны (TYPEOF * xPtr === TypeOf XNode)
  • при чтении исходного кода, ключевые слова и специальные маркеры символов (например, операторы) не count как идентификатор, так как вам не нужно их помнить.(Синтаксис-highligting помогает, тоже)
  • , если есть только один способ выразить свою программу, нет никакой возможности для ошибок, как iPtr *p; p = (qPtr) malloc (sizeof xNode);
  • создавая еще одну-структуру (+ определения типов для него), просто чтобы вместить в корень указатель еще больше закроет ваше ментальное пространство имен.

Теперь переделки из (предполагаемого) Код:

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

struct node { 
    struct node *next; 
    void *payload; 
    }; 

struct node *root=NULL; 

void initialize() { /* nothing .... */ } 

int insert(struct node **pp, void *pv) { 
    struct node *p; 

    p = malloc(sizeof *p); 
    if (!p) { /* handle error */ return -1; } 

    p->payload = pv; 
    p->next = *pp; 
    *pp = p; 
    return 1; /* inserted one element */ 
} 

int main(void) 
{ 
int i; 

i=666; 

/* note: this function call will pass a pointer to a local variable `i` 
** to the insert() function, which will remember it. 
** This is generally a bad idea, to say the least. 
*/ 
insert(&root, &i); 

return 0; 
} 
Смежные вопросы