Hello, I get the following seg fault error when I try to delete the last node of the list. Does anyone know why? My delete function and high level function are included below: The seg fault only occurs when the if value in BeginQuizFirstTry detecting that CheckAnswer is not true or = 0. Can anyone tell me why this seg faults?

int Delete (NODEPTR *headPtr, char *target)
{
   /*  Node pointers that reference the previous node
       and the current node in the list.               */
   NODEPTR prev = NULL, curr = NULL;
    
   /*  Check to see if the list is empty.  */
   if (IsEmpty (*headPtr))
   {
      /*  Display an appropriate message indicating that
	  deleting from the list was not accomplished
	  because the list is empty.                      */
      fprintf (stderr, "Unable to delete from an empty list.\n\n");
      
      /*  If the list is empty, return the integer value
	  of -1, indicating that the question, char
	  *target, was not successfully deleted from the
	  list.                                           */
      return (-1);
   }
   /*  Traverse the list until the target value is found.  */
   else
   {
      /*  Initialize the node pointer referencing a previous
	  node in the list to NULL.                           */
      prev = NULL;
      
      /*  Set the node pointer referencing a current node to
	  the head of the list.                               */
      curr = *headPtr;
      
      /*  First check to see if the question, char *target,
	  that we want to delete is stored in the first
	  node in the list, because this would require
	  *headPtr to be modified.                           */
      if (strcmp ((*headPtr) -> data.question, target) == 0)
      { 
	 /*  If the question, char *target, is stored in the
	     first node in the list, change the head of the
	     list to start at the node pointer referencing
	     the current node's next pointer.                 */
	 *headPtr = curr -> next;
	 
	 /*  Delete and free the memory that was being used
	     to store the question, char *target, in the
	     first node of the list.                         */
	 free (curr);
	 
	 /*  If the question, char *target, was freed and
	     deleted, return the integer value of 1,
	  indicating that the question was successfully
	  deleted from the list.                         */
	 return (1);
      }
      /*  Otherwise, traverse through the list to find the
	  question, char *target, to be deleted.            */
      else
      {
	 /*  Traverse the list if the node pointer
	     referencing the current node in the list is not
	     equal to NULL and the node pointer referencing
	     the current node in the list is not storing the
	     question, char *target, in the data portion of
	     its node.                                        */
	 while ((curr != NULL) &&
		(strcmp (curr -> data.question, target) != 0))
	 {
	    /*  Traverse the list.  */
	    prev = curr;
	    curr = curr -> next;
	 }
	 
	 /*  If the node pointer refencing the current node in
	     the list not equal to NULL, then the question,
	     char *target, was found.                           */
	 if (curr != NULL)
	 {
	    /*  Change the next pointer of the previous node,
		in order to avoid a broken list.               */
	    prev -> next = curr -> next;
	    
	    /*  Delete and free the memory that was being used
		to store the question, char *target, in this
		node of the list.                               */
	    free (curr);
	    
	    /*  If the question, char *target, was freed and
		deleted, return the integer value of 1,
		indicating that the question was successfully
		deleted from the list.                         */
	    return (1);
	 }
	 /*  Otherwise, the question, char *target, was not
	     found in the list.                              */
	 else
	 {
	    /*  If the question, char *target, was not found
		in the list, return the integer value of -1,
		indicating that the question was not
		successfully deleted from the list.           */
	    return (-1);
	 }
      }
   }
}

int BeginQuizFirstTry (NODEPTR *headListPtr1,
		       NODEPTR *headListPtr2,
		       int numberOfTotalQuestions)
{
   /*  A node pointer that will reference the current node
       in the list, starting with the head pointer of the
       first list.                                          */
   NODEPTR curr = *headListPtr1;
   
   /*  A node pointer that will reference a temporary node
       in the list, which will be used for inserting nodes
       into the second list.                                */
   NODEPTR temp;
   
   /*  An array of characters, or a string, which will hold
       the answer that the user inputted for the given
       question that he/she was being asked during the quiz.  */
   char questionAnswer [NUMBEROFANSWERCHARACTERS];
   
   /*  An integer counter variable that will be used to
       label each of the questions in the quiz.          */
   int questionCounter = 0;
   
   /*  An integer counter variable that will be used to
       count the number of questions that the user answered
       correctly during his/her trial of taking the quiz.    */
   int correctAnswerCounter = 0;
   
   /*  A QUIZ structure that will be used to insert each
       question from the first list, into the second list.  */
   QUIZ insertedQuestion;
   
   /*  A float variable that will be used to store the
       user's percentage of correct answers during the
       user's first trial of taking the quiz.           */
   float scoreTrial1;
   
   /*  Display a message indicating that the quiz has
       begun for the user.                             */
   printf ("Here are your questions. Good luck !!!\n\n");
   
   /*  Traverse the list until the end.  */
   while (curr != NULL)
   {
      /*  Increment questionCounter each time a new question
	  from the quiz is presented to the user.             */
      questionCounter++;
      
      /*  Display each of the questions in the quiz to the
	  user.                                             */
      printf ("   %d. ", questionCounter);
      DisplayQuestion (curr);
      
      /*  Read in the user's answer for each of the questions
	  in the quiz.                                         */
      scanf ("%s", questionAnswer);
      
      /*  If the user's answer is not correct, then delete it
	  from the first list and insert it into the second
	  list.                                                */
      if (CheckAnswer (curr, questionAnswer,
		       &correctAnswerCounter) != 1)
      {
	 /*  Copy the original question and correct answer that
	     the user was just being asked into the QUIZ structure,
	     insertedQuestion.                                       */
	 strcpy (insertedQuestion.question, curr -> data.question);
	 strcpy (insertedQuestion.answer, curr -> data.answer);
	 
	 /*  Create enough space in memory for a temporary node
	     that will be inserted into the second list.         */
	 temp = CreateNode ();
	 
	 /*  Store the contents of the original question and
	     correct answer that the user was just being asked
	     into the data portion of the temporary node that
	     was just created.                                  */
	 SetData (temp, insertedQuestion);
	 
	 /*  Insert the temporary node into the second list.  */
	 Insert (headListPtr2, temp);
	 
	 /*  Free the memory that was used to create the temporary
	     node.                                                  */
	 free (temp);
	 
	 /*  Set the node pointer referencing the current node
	     (the current question in the quiz) to point to the
	     next node in the list, or the next question in the
	     quiz.                                               */
	 curr = curr -> next;
	 
	    /*  Delete the question and its correct answer,
		which was just asked to the user, from the first
		list.                                             */
	    Delete (headListPtr1, insertedQuestion.question);
      }
      else
      {
	 /*  Set the node pointer referencing the current node
	     (the current question in the quiz) to point to the
	     next node in the list, or the next question in the
	     quiz.                                               */
	 curr = curr -> next;
      }
   }
   
   /*  Calculate the user's percentage of questions that were
       answered correctly during the first trial of the quiz.  */
   scoreTrial1 = CalculateScore ((float)correctAnswerCounter,
				 (float)numberOfTotalQuestions);
   
   /*  Display the user's score and tell him/her to retry the
       questions that were answered incorrectly.               */
   printf ("Your score is  %.2f%%\n", scoreTrial1);
   printf ("Improve your score by repeating the ones you missed.\n\n\n");
   
   /*  Return the number of questions that were answered
       correctly by the user during this trial so that the
       score can be recalculated in the second trial.       */
   return correctAnswerCounter;
}

Thanks in advance,
Mistro116

Recommended Answers

All 2 Replies

After a ver quick look, I think that you overwrote a pointer - having it point to a bogus address.

malloc works (It's called Doug Lea malloc which is the basis for many versions of malloc) kinda like this:

typedef
union
{
    ptrdiff_t malloc_size;
    void *ptr;
} malloc_t;

The malloc routine returns ptr to your program. When you call free later on, it assumes there is a value in the address immediately "underneath" the pointer. And that it is the same value you started with. Well, if ptr was changed, the value under it could be 0xfffffff, or literally anything else. When free tries to work with the block referenced by ptr, it bumps into memory your process does not own because:

1. ptr references memory you don't own or is read-only
2. malloc_size is the forcing free to reference memory you don't own or is read-only.

After a ver quick look, I think that you overwrote a pointer - having it point to a bogus address.

malloc works (It's called Doug Lea malloc which is the basis for many versions of malloc) kinda like this:

typedef
union
{
    ptrdiff_t malloc_size;
    void *ptr;
} malloc_t;

The malloc routine returns ptr to your program. When you call free later on, it assumes there is a value in the address immediately "underneath" the pointer. And that it is the same value you started with. Well, if ptr was changed, the value under it could be 0xfffffff, or literally anything else. When free tries to work with the block referenced by ptr, it bumps into memory your process does not own because:

1. ptr references memory you don't own or is read-only
2. malloc_size is the forcing free to reference memory you don't own or is read-only.

Thanks, but that has nothing to do with my function. I've malloc'd the data for the node, the pointer is returned fine. That's not the problem. The problem is the segmentation fault at the end of the list. I've come up with some new code, using this delete function.

Can anyone tell me why this doesn't delete the items in the list are wrong when CheckAnswer is evaluated:

int BeginQuizFirstTrial (NODEPTR *headListPtr1,
			 NODEPTR *headListPtr2,
			 int numberOfTotalQuestions)
{
   /*  A node pointer that will reference the current node
       in the list, starting with the head pointer of the
       first list.                                          */
   NODEPTR curr = *headListPtr1;
   
   /*  A node pointer that will reference a temporary node
       in the list, which will be used for inserting nodes
       into the second list.                                */
   NODEPTR temp;
   
   /*  An array of characters, or a string, which will hold
       the answer that the user inputted for the given
       question that he/she was being asked during the quiz.  */
   char questionAnswer [NUMBEROFANSWERCHARACTERS];
   
   /*  An integer counter variable that will be used to
       label each of the questions in the quiz.          */
   int questionCounter = 0;
   
   /*  An integer counter variable that will be used to
       count the number of questions that the user answered
       correctly during his/her trial of taking the quiz.    */
   int correctAnswerCounter = 0;
   
   /*  A QUIZ structure that will be used to insert each
       question from the first list, into the second list.  */
   QUIZ insertedQuestion;
   
   /*  A float variable that will be used to store the
       user's percentage of correct answers during the
       user's first trial of taking the quiz.           */
   float scoreTrial1;
   
   /*  Display a message indicating that the quiz has
       begun for the user.                             */
   printf ("Here are your questions. Good luck !!!\n\n");
   
   /*  Traverse the list until the end.  */
   while (curr != NULL)
   {
      /*  Increment questionCounter each time a new question
	  from the quiz is presented to the user.             */
      questionCounter++;
      
      /*  Display each of the questions in the quiz to the
	  user.                                             */
      printf ("   %d. ", questionCounter);
      DisplayQuestion (curr);
      
      /*  Read in the user's answer for each of the questions
	  in the quiz.                                         */
      scanf ("%s", questionAnswer);
      
      /*  If the user's answer is not correct, then delete it
	  from the first list and insert it into the second
	  list.                                                */
      if (CheckAnswer (curr, questionAnswer,
		       &correctAnswerCounter) != 1)
      {
	 /*  Copy the original question and correct answer that
	     the user was just being asked into the QUIZ structure,
	     insertedQuestion.                                       */
	 strcpy (insertedQuestion.question, curr -> data.question);
	 strcpy (insertedQuestion.answer, curr -> data.answer);
	 
	 /*  Create enough space in memory for a temporary node
	     that will be inserted into the second list.         */
	 temp = CreateNode ();
	 
	 /*  Store the contents of the original question and
	     correct answer that the user was just being asked
	     into the data portion of the temporary node that
	     was just created.                                  */
	 SetData (temp, insertedQuestion);
	 
	 /*  Insert the temporary node into the second list.  */
	 Insert (headListPtr2, temp);
	 
	 /*  Set the node pointer referencing the current node
	     (the current question in the quiz) to point to the
	     next node in the list, or the next question in the
	     quiz.                                               */
	 curr = curr -> next;
	 
	 /*  Make sure the node pointer referencing the current
	     node (the current question in the quiz) contains
	     a node and is not beyond the end of the first list.  */
	 if (curr != NULL && curr -> next != NULL)
	 {
	    
	    /*  Delete the question and its correct answer,
		which was just asked to the user, from the first
		list.                                             */
	    Delete (headListPtr1, insertedQuestion.question);
	 }
      }
      else
      {
	 /*  Set the node pointer referencing the current node
	     (the current question in the quiz) to point to the
	     next node in the list, or the next question in the
	     quiz.                                               */
	 curr = curr -> next;
      }
   }
   
   /*  Destroy the first list and all of its contents, and free
       all of the memory that was allocated to store the node
       data once the user has been asked all of the questions in
       the quiz read from the data file containing the original
       list of questions and correct answers.                     */
   DestroyList (headListPtr1);
   
   /*  Calculate the user's percentage of questions that were
       answered correctly during the first trial of the quiz.  */
   scoreTrial1 = CalculateScore ((float)correctAnswerCounter,
				 (float)numberOfTotalQuestions);
   
   /*  Display the user's score and tell him/her to retry the
       questions that were answered incorrectly.               */
   printf ("Your score is   %.2f%%\n", scoreTrial1);
   printf ("Improve your score by repeating the ones you missed.\n\n\n");
   
   /*  Return the number of questions that were answered
       correctly by the user during this trial so that the
       score can be recalculated in the second trial.       */
   return correctAnswerCounter;
}

Thanks though,

Mistro116

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.