简体   繁体   中英

segmentation fault with linked list

Please see this program given below. It crashes at the end of delete_node function. Please let me know what is going wrong. It crashes at the end of delete_node(5) call. printf statement after call to delete_node is not executed.

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

typedef struct _list{
     int data;
     struct _list *next;
}list;

list* create_list(int val);
list* add_list(int val, bool ad_end);
int  delete_node(int val);
void print_list(void);
list* head = NULL;
list* curr = NULL;

int main()
{
    int val = 10;
    list* mylist;
    mylist = create_list(5);
    add_list(val, true);
    add_list(20, true);
    add_list(30, true);
    add_list(25, true);
    print_list();
    delete_node(5);
    printf("\n I am here in main \n");
    print_list();
    return 0;
}

list* create_list(int val)
{
    list* ptr =(list*) malloc(sizeof(list));
    head = curr = ptr;
    ptr->data = val;
    ptr->next = NULL;
    return ptr;
}

list* add_list(int val, bool add_end)
{
    list* ptr =(list*) malloc(sizeof(list));
    ptr->data = val;
    ptr->next = NULL;
    if(add_end) {
        curr->next = ptr;
        curr = ptr;
    } else {
        ptr->next = head;
        head = ptr;
    }
    return ptr;
}

int delete_node(int val)
{
    list* tmp = NULL;
    list* prev;

    tmp = head;
    while(tmp){
        if( tmp->data == val) {
            printf(" Found the node to be deleted\n");
            prev->next = tmp->next;
            if( tmp == head) {
                head = tmp->next;
            }
            free(tmp);
            printf(" Head data is %d \t head %p\t add-nxt %p\n", head->data, head, head->next);
            break;
        } else {
            prev = tmp;
            tmp = tmp->next;
        }
        printf("Node to be deleted not found \n");
    }
    return 1;
}

void print_list(void)
{
    list* tmp = head;
    while(tmp != NULL) {
        printf("addr %p\t addr next %p\n", tmp, tmp->next);
        printf(" Data is %d \n", tmp->data);
        tmp = tmp->next;
    }
    printf("\n");
}

Here is your code after correction it is working absolutely fine now, by the way this is not a good way of making the linked list.

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

typedef struct _list{
     int data;
     struct _list *next;
}list;

list* create_list(int val);
list* add_list(int val, bool ad_end);
int  delete_node(int val);
void print_list(void);
list* head = NULL;
list* curr = NULL;

int main()
{
    int val = 10;
    list* mylist;
    mylist = create_list(5);
    add_list(val, true);
    add_list(20, true);
    add_list(30, true);
    add_list(25, true);
    print_list();
    delete_node(5);
    printf("\n I am here in main \n");
    print_list();
    return 0;
}

list* create_list(int val)
{
    list* ptr =(list*) malloc(sizeof(list));
    head = curr = ptr;
    ptr->data = val;
    ptr->next = NULL;
    return ptr;
}

list* add_list(int val, bool add_end)
{
    list* ptr =(list*) malloc(sizeof(list));
    ptr->data = val;
    ptr->next = NULL;
    if(add_end&&head!=NULL) {

          while(curr->next!=NULL){
               curr= curr->next;

                }
        curr->next=ptr;
        curr = ptr;
    } else {
        ptr->next = head;
        head = ptr;
    }
    return ptr;
}

int delete_node(int val)
{
    list* tmp = NULL;
    list* prev;

    tmp = head;
    while(tmp->next!=NULL){
         prev=tmp;

           if( tmp == head&&head->next!=NULL) {
                head = tmp->next;

            free(tmp);
            printf(" Head data is %d \t head %p\t add-nxt %p\n", head->data, head, head->next);
            break;
          }

          if( tmp->data == val) {
            printf(" Found the node to be deleted\n");
               tmp=tmp->next;
             prev->next=tmp->next;
             free(tmp);
             printf(" Head data is %d \t head %p\t add-nxt %p\n", head->data, head, head->next);
            break;  

        } else{
        printf("Node to be deleted not found \n");
}
    }
    return 1;
}

void print_list(void)
{
    list* tmp = head;
    while(tmp != NULL) {
        printf("addr %p\t addr next %p\n", tmp, tmp->next);
        printf(" Data is %d \n", tmp->data);
        tmp = tmp->next;
    }
    printf("\n");
}

Kindly go through this linked list implemented by me, which I believe will be much simpler to understand and code

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


  struct node{

        char data;
        struct node *next;  
         };

    struct node *head=NULL;



    void printMenu();
    void getUserSelection(int *);
    void performOperation(int );
    void display(void);
    void addNodeAtBeginning(void);
    struct node* createNode(void);
    void  displayLinkedList(void);
    void addNodeAtEnd(void);
    void getDataFromUser(char*);
    void addAtuserSpecificLocation(void);
    int  getLocationFromUser(void);
    void deleteFirstNode(void);
    void deleteLastNode(void);
    void deleteFromAspecificPosition(void);
    void deleteEntireList(void);

int main(){


    int option=0;


    while(9!=option){
                     printMenu();
                     getUserSelection(&option);
                     performOperation(option);
    }


    getchar();

    return 0;


}

void printMenu(){


      printf("\n");
      printf("\n***********MENU***************\n");
      printf("1) Add a node at the beginning\n");
      printf("2) Add a node at the end\n");
      printf("3) Add a node at a user selected position\n");
      printf("4) Delete first Node\n");
      printf("5) Delete last Node\n");
      printf("6) Delete node at a user selected position\n");
      printf("7) Display\n");
      printf("8) Delete entire list\n");
      printf("9) Exit");

      }

 void getUserSelection(int *number){

      printf("\nSelect an option: ");
      scanf("%d",number);

      }

void  performOperation(int option){

      switch(option){
                     case 1:
                          addNodeAtBeginning();
                          break;

                     case 2:
                          addNodeAtEnd();
                          break;

                     case 3:
                          addAtuserSpecificLocation();
                          break;

                     case 4:
                          deleteFirstNode();
                          break;

                     case 5:
                          deleteLastNode();
                          break;

                     case 6:
                          deleteFromAspecificPosition();
                          break;

                     case 7:
                          displayLinkedList();
                          break;

                     case 8:
                          deleteEntireList();
                          break;

                     case 9:
                          exit(0);
                          break;

                          default:
                                  printf("\n\n********Invalid option**************\n\n");
                                  break;



                }



      }



      void addNodeAtBeginning(void){

                    struct node *tempNode=NULL;
                    if(NULL==head)  {

                                    head= createNode();
                                    }else{
                                          tempNode=createNode();
                                          tempNode->next=head;
                                          head=tempNode;


                                          }   


                            }     


   void addNodeAtEnd(){
                 struct node*tempNode=NULL;

                  if(NULL==head)  {
                                  head=createNode();
                                  }else{
                                       tempNode=head;
                                       while(NULL!=tempNode->next){
                                                    tempNode=tempNode->next;               

                                                                   } 

                                                                   tempNode->next=createNode();



                                        }

                 }              

   struct node* createNode(){
             struct node *tempNode;

             tempNode= (struct node*)malloc(sizeof(struct node));
             getDataFromUser(&tempNode->data);
             tempNode->next=NULL;
             return tempNode;

             }

 void displayLinkedList(){
                     struct node *tempNode;
                     printf("\n\n********************LINKED_LIST_DOUBLY*******************************\n\n\n");

                     tempNode=head;

                     printf("[head]-->");
                     while(NULL!=tempNode->next){

                                          printf("[%c]", tempNode-> data);
                                          printf("--->");
                                          tempNode=tempNode->next;     


                     }
                     printf("[%c]", tempNode->data);
                     printf("-->[X]");
                     printf("\n\n********************LINKED_LIST_DOUBLY*******************************\n\n\n");


                     }


void getDataFromUser(char * data){

                 fflush(stdin);
                 printf("Enter data: ");
                 scanf("%c",data);  

                     }

void addAtuserSpecificLocation(void){

     int location;
     struct node *tempNode=NULL;
     struct node *tempUserNode=NULL;
     tempNode=head;
     location=getLocationFromUser();

     int i;
     for(i=1;i<location-1;i++){
             tempNode=tempNode->next;

             }

     tempUserNode=createNode();
     tempUserNode->next=tempNode->next;
     tempNode->next=tempUserNode;

     }

 int getLocationFromUser(void){
     int location;
     int linkedListLength;
     linkedListLength=getLengthOfLinkedList();
     while(location<0||location>linkedListLength){
     printf("\n\nEnter a valid location: ");
     scanf("%d",&location);
     }

     return location;



 }

 int getLengthOfLinkedList(){
     struct node *temp;
     int length=1;
     if(NULL==head){
                    printf("\n\nLinked list is empty cannot perform operation\n\n");
                    }else{
                     temp=head;


     while(temp->next!=NULL){
                     length++;
                     temp=temp->next;       
                             }
                             }
     return length;


     }

  void deleteFirstNode(void){

       struct node *tempNode=NULL;

       if(NULL!=head){
                      tempNode=head;
                      head=head->next;
                      free(tempNode);

                      }else{

                            printf("\n\nThere is no node to delete\n\n");

                            }

       }

void deleteLastNode(void){

     struct node *tempNode;

     if(NULL!=head){
               tempNode=head;

               while(NULL!=tempNode->next){
                                         tempNode=tempNode->next;  
                                           }

                                           free(tempNode);


                    }else{

                           printf("\n\nThere is no node to delete\n\n");
                           }


     }

     void deleteFromAspecificPosition(void){

     int location;
     struct node *tempNode;

     if(NULL!=head){
               tempNode=head;  
                  location = getLocationFromUser();
                  int listIterator=0;
                  for(listIterator=0; listIterator<location-1;listIterator++){
                          tempNode=tempNode->next;

                                   }

                                   free(tempNode);

                                   }
}

 void deleteEntireList(void){

      struct node* tempNode;
      struct node* tempNode2;
      if(NULL==head){
                     printf("\n\nList is already empty\n\n");


                     }else{
                           tempNode=head;

                           while(tempNode->next!=NULL){
                                tempNode2=tempNode->next;
                                free(tempNode);
                                tempNode=tempNode->next;

                                                 }
                                                 free(tempNode2);
                                                 head=NULL;
                           printf("\n\nList Deleted\n\n");

                           }


      }

In delete_node(int val) the prev pointer is not initialised. The statement prev->next = tmp->next; gives undefined behaviour. Initialise the pointer:

list * prev = head;

Also the printf statement follows the free(tmp); statement. printf is printing variables in memory which have already been de-allocated. The free call should follow the printf statement.

 printf(" Head data is %d \t head %p\t add-nxt %p\n", head->data, head, head->next);
 free(tmp);

In delete_node , you declare variable prev , but you do not assign any value to it:

list* prev;

As the required value (5) is in the first list element, it will execute this statement:

prev->next = tmp->next;

with prev undefined, therefore unleashing SegmentFault.

That's what's causing the error.

The simplest solution is just to handle the case when wanted element is the first one by setting prev to NULL in declaration and checking if it is NULL in the while loop:

...
int delete_node(int val)
{
    list* tmp = NULL;
    list* prev = NULL;

    tmp = head;
    while(tmp){
        if( tmp->data == val) {
            printf(" Found the node to be deleted\n");
        if (prev) {
             prev->next = tmp->next;
        }
        ...

You should also consider doing it without global variables.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM