链表的分段错误

时间:2013-07-29 09:54:21

标签: c linked-list

请参阅下面给出的这个程序。它在delete_node函数结束时崩溃。请告诉我出了什么问题。它在delete_node(5)调用结束时崩溃。调用delete_node后的printf语句未执行。

#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");
}

3 个答案:

答案 0 :(得分:3)

以下是修正后的代码现在工作得非常好,顺便说一下这不是制作链表的好方法。

#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");
}

请仔细阅读我实施的链接列表,我相信这将更容易理解和编码

#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");

                           }


      }

答案 1 :(得分:1)

delete_node(int val)中,prev指针未初始化。语句prev->next = tmp->next;给出了未定义的行为。初始化指针:

list * prev = head;

此外,printf语句遵循free(tmp);语句。 printf在内存中打印已经解除分配的变量。免费电话应该遵循printf声明。

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

答案 2 :(得分:1)

delete_node中,您声明变量prev,但您没有为其指定任何值:

list* prev;

由于所需的值(5)位于第一个list元素中,它将执行以下语句:

prev->next = tmp->next;

prev未定义,因此释放SegmentFault。

这就是造成错误的原因。

最简单的解决方案就是通过在声明中将prev设置为NULL并检查while循环中是否为NULL来处理所需元素是第一个的情况:

...
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;
        }
        ...

你也应该考虑在没有全局变量的情况下这样做。