Ошибка сегмента и логические ошибки

#c #linked-list

#c #связанный список

Вопрос:

Я создаю программу связанного списка, которая использует несколько функций для упрощения добавления или удаления узлов из списка. Я считаю, что моя логика в порядке с выделением и добавлением нового узла, но я все еще получаю ошибку seg. Не могли бы вы просмотреть мою логику и объяснить, что вызывает ошибку seg? Я очень неопытен в связанных списках. Спасибо!

Это мои объявления функций

 #define SIMPLELL_H

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

typedef struct Node
{
  int data;
  struct Node *next;
}node_t;

node_t* head;

void printList();
void append(int num);
void addFront(int num);
void deleteList();
void removeNode(int num);
int length();



#endif
 

Это определения функций

 void printList(){
  // declare temp to traverse the LL and print each value
  node_t *temporary = head;
  while(temporary != NULL){
    printf("%d, ", temporary->data);
    temporary = temporary->next;
  }
  if (head == NULL){
    printf("This list is empty.n");
  }
}
void append(int num){
  //declare temporary pointer to traverse LL
  node_t *tmp = head;
  node_t *prev = NULL;
  //malloc the new node
  node_t *new = malloc(sizeof(node_t));
  if(head == NULL){
    //initialize the new node
    new->data = num;
    new->next = NULL;

    head->next = new;
  }
  else{
    //initialize the new node
    new->data = num;
    new->next = NULL;
    //loop to traverse to the last value in the node
    while(tmp != NULL){
      prev = tmp;
      tmp = tmp->next;
    }
    prev->next = new;
  }
}
void addFront(int num){
  //allocate memory for new node and allocate local variable equal to head
  node_t *new = malloc(sizeof(node_t));
  new->data = num;
  new->next = head;
  head = new;
}
void deleteList(){
  node_t *tmp = head;
  node_t *prev = NULL;
  while(tmp != NULL){
    prev = tmp;
    tmp = tmp->next
    free(prev);
  }
}
void removeNode(int num){
//temp is used to traverse the ll until I find the node with the value
//then the previous value is linked to the next value removing the middle value.
  node_t *temp = head;
  node_t *prev = NULL;
  if(head == NULL){
    printf("List is not initializedn");
    return;
  }
  while(temp->data != num){
    prev = temp;
    temp = temp->next;
    if (temp->data == num){
      prev->next = temp->next;
      free(prev);
    }
    else{
      printf("Value is not in the listn");
      return;
    }

}
int length(){
  int length = 0;
  node_t *temp = head;
  while (temp != NULL){
    length  = 1;
    temp = temp->next;
  }
  return length;
}
 

Это функция драйвера, которую мне не нужно менять

 #include "SimpleLL.h"
#include "SimpleLL.c"
int main()
{
  /*head is a global variable*/
  head = NULL;
  int size =0;
  removeNode(1);
  append(2);
  append(3);
  addFront(1);
  append(4);
  printList();
  size = length();
  printf("size now %dn",size);
  removeNode(8);
  printList();
  removeNode(1);
  printList();
  removeNode(4);
  printList();
  deleteList();
  printList();
  size = length();
  printf("size after deletion %dn",size);

  return 0;
}
 

Комментарии:

1. /*head is a global variable*/ Это очень плохая идея.

2. Рассмотрим, что происходит, append когда «список» пуст. Какое значение prev имеет?

3. Это должно быть просто NULL правильно? В этом случае я должен использовать оператор if, чтобы указать, когда head/prev значение равно NULL?

4. Это помогло бы. Также обратите внимание, что printList это всегда будет печататься "This list is empty.n" в конце. Это может быть не ожидаемое поведение.

5. Итак, я отредактировал свою функцию добавления, чтобы включить этот оператор if, однако я все еще получаю ошибку seg. Я знаю, что эта ошибка seg возникает в функции добавления, однако я все еще не уверен, что является ее причиной. Я предполагаю, что это моя функция malloc, но я не уверен, почему это вызывает ошибку seg.

Ответ №1:

removeNode не содержит теста для достижения конца списка. Поэтому, если значение не найдено в списке, оно разыменует нулевой указатель в конце и завершится сбоем.

Это будет иметь место в самом первом тесте, который пытается удалить узел, когда список пуст, а также для removeNode(8) .

Ваша removeNode функция также нуждается в free() удаленном узле. В настоящее время он освобождает узел, который появился после удаленного, который все еще находится в списке и вызовет неопределенное поведение при последующем доступе к нему.

Комментарии:

1. Спасибо за быстрый ответ. Теперь я исправил это, но после этого моя функция все еще выдает ошибки. Я думаю, что есть проблема с моей функцией добавления узла, но я не уверен, что это такое. Я скоро обновлю свой пост

2. @Arock475: Вы не исправили это — теперь, что произойдет, если список не пуст, но нужного числа в нем нет? Как и в случае с removeNode(8) .

3. Вы абсолютно правы, я об этом не подумал. Спасибо

4. @Arock475: Ваша free() ошибка неверна — см. Редактирование.

5. Я думаю, что я исправил проблему с free(), а также исправил ее так, чтобы, если значения нет в связанном списке, оно правильно печатало сообщение об ошибке и завершало работу.