AddressSanitizer: ошибка DEADLYSIGNAL для связанного списка в C

#c #data-structures #linked-list

#c #структуры данных #связанный список

Вопрос:

Я пытаюсь создать связанный список на C, где он считывается из входного файла и либо добавляет, либо удаляет узлы. Я получаю ошибку AddressSanitizer: DEADLYSIGNAL (на фото), которая, как я думаю, связана с разыменованием нулевого указателя в моей функции insert node, но я не могу найти, где я это делаю. Если я ошибаюсь в том, что означает эта ошибка, или вы видите, где я ошибаюсь, это было бы огромной помощью. Большое спасибо!!

»’

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

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

void printList(Node *head){
  Node *temp = head->next;
  int count;
  while(temp != NULL){
    temp = temp->next;
    count  ;
  }
  printf("%dn", count);
  temp = head->next;
  while(temp != NULL){
    printf("%dt", temp->data);
    temp = temp->next;
  }
}

Node *makeNode(int value){
  Node *newNode = malloc(sizeof(Node));
  newNode->data = value;
  newNode->next = NULL;
  return newNode;
}

void insertNode(Node *head, Node *newNode){
  Node *temp ,*prev;
  temp = head;
  while(temp != NULL amp;amp; temp->data <= newNode->data) {
    prev = temp;
    temp = temp->next;
  }
  newNode->next = temp;
  prev->next = newNode;
}

void deleteNode(Node *head, int deleteNum){
  if(head->next != NULL){
    if(head->next->data == deleteNum){
      head->next = head->next->next;
      free(head->next);
    }
    else{
      //printf("hello");
      Node *temp ,*prev;
      temp = head;
      while(temp != NULL amp;amp; temp->data != deleteNum) {
        prev = temp;
        temp = temp->next;
      }
      if(temp != NULL){
        prev->next = temp->next;
        //free(temp);
      }
    }
  }
}

int main(int argc, char* argv[])
{
  Node* head = malloc(sizeof(Node));
  Node *temp;
  char* filename = argv[1];
  if(fopen(filename, "r") == NULL){
    printf("error");
  }
  else{
  FILE* fp = fopen(filename, "r");
  char mode;
  int tempData;

  while (fscanf(fp, "%ct%dn", amp;mode, amp;tempData ) == 2) {
    //printf("%cn", mode);
    if(mode == 'i'){
      //printf("%cn", 'i');
      Node *insert = makeNode(tempData);
      insertNode(head, insert);
    }
    else if(mode == 'd'){
      //printf("%cn", 'd');
      //printList(head);
      deleteNode(head, tempData);
      //printList(head);
    }
  }
  printList(head);
}
}
  

»’
Изображение ошибки

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

1. Можете ли вы предоставить входные данные, которые вызывают сбой?

Ответ №1:

Вы никогда не инициализируете узел, который head указывает на in main , поэтому, когда вы передаете его insertNode , значение head->next может быть мусором; в частности, оно может быть не нулевым. В этом случае while цикл будет выполняться как минимум две итерации, устанавливая temp указатель на мусор head->next , и доступ temp->data к условию while разыменования этого указателя на мусор. Отсюда и сбой.

Вы, вероятно, хотите head->next = NULL; где-то main после malloc , но перед insertNode . Или, что еще лучше, используйте существующую makeNode функцию для выделения head .

Существует еще одна ошибка, заключающаяся в том, что вы также никогда не инициализируете head->data , с которой сравнивается newNode->data . Если мусор в head->data больше, чем newNode->data , insertNode попытается вставить его в список до head , что не сработает и просто приведет к потере узла. Кроме prev того, будет использоваться неинициализированный, что, вероятно, также приведет к сбою. Вы могли бы обойти это, инициализировав head->data to INT_MIN , но было бы лучше исправить логику insertNode , чтобы она никогда не сравнивалась с head->data в первую очередь. deleteNode имеет аналогичную проблему.

Еще одна бонусная ошибка: count неинициализируется printList .

Вы могли бы обнаружить последние ошибки, скомпилировав с -Wall -O ; затем gcc обнаружит и предупредит о неинициализированных переменных. valgrind также обнаружена printList ошибка для меня.