Segmentation Fault Error in C

让人想犯罪 __ 提交于 2019-12-11 14:06:57

问题


Hi i'm a new programmer for C, i get a segmentation fault in my linked list program, i was wondering if anyone could help me out. I've posted my code below... If you need furthure information I will post it. Thanks.

#include "list.h"

//+-------------------------------------------------------------
//+ CREATE NODE
//+
//+ Allocate memory for a node of type struct node and 
//+ initialize it with d. Return a pointer to the new node.
//+-------------------------------------------------------------
struct node* createNode(int d){
  struct node* newNode = malloc(sizeof(struct node)); //create and allocate space in memory for a new node called newNode

  newNode->item = d; //newNode's data is the value stored in 'd'
  newNode->next = NULL; //sets the pointer to the next node to NULL

  return newNode; //return the new node created
}

//+-------------------------------------------------------------
//+ INSERT HEAD NODE
//+
//+ Insert Node n in front of the head of the list, and set
//+ n to be the new head of the list.
//+-------------------------------------------------------------
void insertHead(struct node **headRef, struct node *n){
  struct node* newNode = malloc(sizeof(struct node)); //create and allocate space in memory for a new node called newNode

  newNode->item = n->item; //newNode's data is assigned the value of the parameter node n''
  newNode->next = *headRef; //since we are inserting the node at the head we set the next node to be the head reference
  *headRef = newNode;   //and then we assign the head reference to the new node created, thus, inserting the head node
}

//+-------------------------------------------------------------
//+ INSERT TAIL NODE
//+
//+ Insert Node n at the tail of the LinkedList.
//+-------------------------------------------------------------
void insertTail(struct node **headRef, struct node *n){
  struct node* newNode = malloc(sizeof(struct node)); //create and allocate space in memory for a new node called newNode
  newNode = *headRef;   //the new node is now the head reference

  while(newNode->next != NULL)  //while the next node is not equal NULL
 newNode = newNode->next; //set the newNode to the next node (this finds the last node)

  struct node* tmp = malloc(sizeof(struct node)); //create and allocate space in memory for a new node called tmp

  tmp->item = n->item;   //the data of tmp is assigned the data of the parameter node 'n'
  tmp->next = NULL;   //the node following tmp is set to NULL
  newNode->next = tmp;   //tmp is now set to the next node, thus, becoming the last node i.e. the tail
}

//+-------------------------------------------------------------
//+ COUNT NODES IN LINKED LIST
//+
//+ Count the # of nodes that are part of the LinkedList.
//+-------------------------------------------------------------
int countNodes(struct node *headRef){
  int counter = 0; //create a counter variable to store the number of nodes

  struct node* current = headRef; //create a new node and assign it the reference to the head node

  if(headRef = NULL) return 0;  //if the head is NULL, return 0 (no nodes if no head)

  while(current != NULL){  //while the current node is not NULL
 counter++;   //increment the counter
 current = current->next; //and move on to the next node, thus, adding 1 to the counter with each node passed
  }
  return counter; //return the total number of nodes, stored in counter
}

//+-------------------------------------------------------------
//+ FIND NODE
//+
//+ Return the first node that has item = val, return NULL 
//+ otherwise.
//+-------------------------------------------------------------
struct node* findNode(struct node *head, int val){
  struct node* tmp = malloc(sizeof(struct node)); //create and allocate space in memory for a new node called tmp

  *tmp = *head;   //node tmp is now referring to the head node of the list

  while(tmp != NULL)  //while the tmp node is not equal to NULL
  {
 if(tmp->item == val){ //if the data of the tmp node is equal to the value sent as parameter 
  return tmp; //return the tmp node
 }else{
  return NULL; //otherwise, return NULL
 }  
   tmp = tmp->next; //set the tmp node to the next node in the list (traversing)
  }
}

//+-------------------------------------------------------------
//+ DELETE NODE
//+
//+ Delete node n from the list and free memory allocated to n.
//+-------------------------------------------------------------
void deleteNode(struct node **headRef, struct node *n){
 struct node* toBeDeletedNode = malloc(sizeof(struct node)); //create and allocate space in memory for a new node called toBeDeletedNode

 toBeDeletedNode = findNode(*headRef, n->item); //toBeDeletedNode is set to equal the node findNode() returns
       //this node should be the node with its data = to the data of the parameter node n
 free(toBeDeletedNode); //delete node toBeDeletedNode references and free the space allocated it
}

Here is the test file....

#include "list.h"
#include <assert.h>
#include <sys/types.h>
#include <stdio.h>

// create and insertHead
void test1() 
{
 struct node *headRef=NULL;
    struct node *nptr = NULL;
 int h=0;

 while(h<5)
      insertHead(&headRef,createNode(h++));
 h = 0;
 for (nptr = headRef; nptr != NULL; nptr = nptr->next, h++) 
  assert(nptr->item == (4 - h) );
 assert(h==5);

 printf("HAHA");
}

// create and insertTail
void test2() 
{
 struct node *headRef=NULL;
    struct node *nptr = NULL;
 int h=0, t=0;

 while(h<5)
      insertTail(&headRef,createNode(h++));

 h = 0;
 for (nptr = headRef; nptr != NULL; nptr = nptr->next, h++) 
  assert(nptr->item ==  h);
 assert(h==5);
 printf("HAHA");
}

// countNodes 
void test3() 
{
 struct node *headRef=NULL;
    struct node *nptr = NULL;
 int h=0, t=0;

 while(h<50)
      insertTail(&headRef,createNode(h++));
 h = 0;
 for (nptr = headRef; nptr != NULL; nptr = nptr->next, h++) 
  assert(nptr->item ==  h);
 assert(countNodes(headRef) == 50);
}

// findNode 
void test4() 
{
 struct node *headRef=NULL;
    struct node *nptr = NULL;
 int h=0;

 nptr = findNode(headRef, 1);
 assert(nptr == NULL);

 while(h<50)
      insertTail(&headRef,createNode(h++));


 nptr = findNode(headRef, 10);
 assert(nptr != NULL);
 assert (nptr->item = 10);

 nptr = findNode(headRef, -10);
 assert(nptr == NULL);
}

// deleteNode 
void test5() 
{
 struct node *headRef=NULL;
    struct node *nptr = NULL;
 int h=0;

 while(h<5)
      insertTail(&headRef,createNode(h++));

 h = 0;
 while(h<5) {
  nptr = findNode(headRef, h);
  assert(nptr != NULL);
  deleteNode(&headRef, nptr);
  assert(findNode(headRef, h) == NULL);
  assert(countNodes(headRef) == (4 - h));
  h++;
 }
}

/*// sort
void test6() 
{
 struct node *headRef=NULL;
    struct node *nptr = NULL;
 int h=0;
 int d[5] = {1, 0, -1, 5, 100};
 int ds[5] = {-1, 0, 1, 5, 100};

 while(h<5)
      insertTail(&headRef,createNode(d[h++]));

   sort(&headRef);

 h = 0;
 for (nptr = headRef; nptr != NULL; nptr = nptr->next, h++) 
  assert(nptr->item ==  ds[h]);
}*/

int main( int argc, char ** argv )
{
    int testNum = 0;

    if ( argc < 2 ) {
        fprintf(stderr, "\n usage: %s test-num\n", argv[0]);
        return 1;
    }

   testNum = atoi(argv[1]);
   switch(testNum){
        case 1:
                test1();
                break;
        case 2:
                test2();
                break;
        case 3:
                test3();
                break;
        case 4:
                test4();
                break;
        case 5:
                test5();
                break;
        case 6:
                //test6();
                break;

        default:
                fprintf(stderr, "\n usage: %s 1 .. 8\n", argv[0]);
                 return 1;
   }
   return 0;
}

回答1:


I don't know if this is the error, but this line is almost certainly wrong:

  if(headRef = NULL) return 0;  //if the head is NULL, return 0 (no nodes if no head)

and should be

  if(headRef == NULL) return 0;  //if the head is NULL, return 0 (no nodes if no head)

It's in countNodes().




回答2:


There are quite a few issues here.

You are allocating new nodes when you should almost certainly not be, in insertHead, insertTail, findNode, and deleteNode. None of these functions should allocate anything (unless you genuinely want to copy the caller's nodes, which I doubt, in which case you should allocate in insertHead and insertTail, but not the other two, and you should use your own createNode function to do that). Ordinarily I would expect the insertHead function, for example, to simply take the passed-in node and insert it at the head of the list; it would not typically allocate a new node and copy the passed-in node's contents.

The insertTail function needs some work. It leaks a node each time and, I think, it crashes if you append to an empty list (the case in which the new tail is also the new head). Try something like:

void insertTail(struct node **head, struct node *n)
{
  struct node **tmp = head;

  while (*tmp != NULL)
  {
    tmp = &((*tmp)->next);
  }

  *tmp = n;
  n->next = NULL;
}

In countNodes you have if (headRef = NULL) but that should be ==, not =.

There's no testing for alloc failures (though this is unlikely to be the cause of your segfault).

Personally, I would use calloc rather than malloc so that your new nodes have zeroed contents.

Your deleteNode function will seqfault if its call to findNode returns NULL.

I'd recommend adding in some asserts, for example:

void insertHead(struct node **head, struct node *n)
{
  assert(head != NULL);
  assert(n != NULL);
  assert(n->next == NULL);

  n->next = *head;
  *head = n;
}

I'd recommend adding in some debugging aids, for example:

void printNodes(struct node *head)
{
  int count = 0;

  while (head != NULL)
  {
    printf("Item[%d] at %p = %d\n", ++count, head, head->item);
    head = head->next;
  }
}



回答3:


struct node* tmp = malloc(sizeof(struct node));

where ever you have used this you are creating a blunder, malloc according to the ANSI spec returns the pointer to the allocated address, and you have to manually typecast it to the type that you wish it to be, the correct syntax is

struct node* tmp = (struct node*)malloc(sizeof(struct node));

you are also doing this

*tmp = *head;

you have to assign the pointers NOT the actual values contained at the corresponding memory locations, so write tmp=head because according to the standards, *p denotes the value of the location pointed by the pointer

also bad programming style, you are allocating memory in each and every function, you can create one pointer and allocate memory only once in the main function and then use it in your functions

a nice tips tutorial on segmentation error is here



来源:https://stackoverflow.com/questions/4821013/segmentation-fault-error-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!