0

I have been working on a C program for an assignment in my CS class, which compiles successfully but gets a segmentation fault error upon running. The assignment deals with linkedLists; we had to take methods described and declared in a header file called linkedlist.h and implement them a file called linkedlist.c. A file called listtest.c is provided and used to test the method.

My Code (linkedlist.c, the comments are from the header file we were given describing how the methods should work):

#include "linkedlist.h"
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>


/* Alloc a new node with given data. */
struct ListNode* createNode(int inputData)
{

    struct ListNode *newNodeCN;
    newNodeCN->data = inputData;
    return newNodeCN;
}

/* Insert data at appropriate place in a sorted list, return new list head. */
struct ListNode* insertSorted(struct ListNode* head, int inputData)
{
    printf("insertsorted started \n");

    struct ListNode * nextIS = NULL;
    struct ListNode * newNodeIS = NULL;
    struct ListNode * currIS = head;
    struct ListNode * listHeadIS = currIS;
    if (currIS == NULL)
    {
        listHeadIS = createNode(inputData);
        return listHeadIS;
    }
    while (currIS->next != NULL)
    {
        nextIS = currIS->next;

        if (currIS->data < inputData)
        {
            if (nextIS->data >= inputData)
            {

                nextIS->next = createNode(inputData);
                newNodeIS = nextIS->next;
                if (newNodeIS->data > listHeadIS->data)
                {
                    listHeadIS = newNodeIS;
                }
            }
        }
        currIS = currIS->next;
    }

    return listHeadIS;
}

/* Remove data from list pointed to by headRef, changing head if necessary.
* Make no assumptions as to whether the list is sorted.
* Memory for removed node should be freed.
* Return 1 if data was present, 0 if not found. */
int removeItem(struct ListNode** headRef, int data)
{
    struct ListNode * tempRem = *headRef;
    int filterVal = data;

    while (tempRem->next != NULL)
    {
        if (tempRem->data == filterVal)
        {
            free(tempRem);
            tempRem = tempRem->next;
            return 1;
        }
    }


    return 0;
}
/* Insert data at head of list, return new list head. */
struct ListNode* push(struct ListNode* head, int data)
{
    printf("push started \n");
    int dataPush = data;

    struct ListNode * tempPush = (struct  ListNode*)malloc(sizeof(struct ListNode));
    tempPush->data = dataPush;
    tempPush->next = head;
    *head = *tempPush;
    return tempPush;
}

/* Remove and return data from head of non-empty list, changing head.
* Memory for removed node should be freed. */
int pop(struct ListNode** headRef)
{
    struct ListNode * tempPop = *headRef;
    int tempData;

    tempData = tempPop->data;
    free(tempPop);
    tempPop = tempPop->next;

    return tempData;
}
/* Return length of the list. */
int listLength(struct ListNode* head)
{
    int i;
    while (head->next != NULL)
    {
        i++;
        head = head->next;
    }
    return i;
}
/* Print list data on single line, separated with spaces. */
void printList(struct ListNode* head)
{
    printf("PrintList Started \n");
    if (head != NULL)
    {

        while (head->next != NULL)
        {

            printf("%d\n", head->data);
            head = head->next;
        }
    }
}
/* Free memory used by the list. */
void freeList(struct ListNode* head)
{
    while (head != NULL)
    {
        free(head);
        head = head->next;
    }
}
/* Reverse order of elements in the list */
void reverseList(struct ListNode** headRef)
{
    struct ListNode * origRL = *headRef;
    struct ListNode * nextRL = NULL;
    struct ListNode * prevRL = NULL;
    while (origRL->next != NULL);
    {
        nextRL = origRL->next;
        prevRL = origRL;
        origRL = nextRL;
        origRL->next = prevRL;
   }

}

The code from listtest.c (I did not write this):

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

int main(int argc, char** argv)
{
  int i, n;
  struct ListNode* head = NULL;
  struct ListNode* stack = NULL;

  printf("empty list: ");
  printList(head);

  for(i = 0; i < 23; ++i)
  {
    n = (i*17+11) % 23;
    head = insertSorted(head, n);
    printf("sort succesful /n");
    stack = push(stack, n);
  }

  printf("filled list: ");
  printList(head);
  printf("list length = %d\n", listLength(head));

  printf("filled stack: ");
  printList(stack);
  printf("stack size = %d\n", listLength(stack));

  for(i = -4; i < 25; i+=4)
  {
    n = removeItem(&head, i);
    if(!n) printf("remove did not find %d\n", i);  
  }

  printf("list after removes: ");
  printList(head);
  printf("list length = %d\n", listLength(head));

  for(i = 0; i < 5; ++i)
  {
    printf("pop: %d\n", pop(&stack));
  }

  printf("stack after pops: ");
  printList(stack);
  printf("stack size = %d\n", listLength(stack));

  reverseList(&head);
  printf("list after reverse: ");
  printList(head);

  freeList(head);
  head = NULL;

  freeList(stack);
  stack = NULL;

  return 0;
}

According to both Valgrind and GDB the segmentation fault is being caused by something in main. Valgrind gives me the error:

 Access not within mapped region at address 0x6FFFFFFE3
==6300==    at 0x400953: main 

My question is what exactly is causing the segmentation fault, how could I fix it, and could anything else in my code cause a segmentation fault? I am not allowed to edit listtest.c, so any changes will have to be in linkedlist.c. Thank You.

1
  • obviously you havent compiled with debug symbols (option -g). also your probably supposed to call createnode before insertSorted Commented Nov 17, 2013 at 5:45

3 Answers 3

1
  1. struct ListNode *newNodeCN; newNodeCN->data = inputData; No new node is actually allocated

  2. int listLength(struct ListNode* head) - i is never initialized.

  3. oid freeList(struct ListNode* head) - free, then dereference

Sign up to request clarification or add additional context in comments.

2 Comments

I changed *newNodeCN; to struct ListNode *newNodeCN = (struct ListNode*)malloc(sizeof(struct ListNode)); and I initialized i in listLength to 0. This fixed the segmentation fault, and now the program runs further but then hits another segmentation fault. What do you mean by free and then dereference? Isn't the while loop in freeList doing that?
yep, but you're doing it in the wrong order: you free() the object (so it no longer exists), then you ask for its member by head->next! actually you do this in removeItem() as well.
0

In function insertSorted , the condition if (newNodeIS->data...) derefferences the pointer without verifing it's not NULL , thatay be the source of the segmentation fault. try fixing that the report back :)

2 Comments

I added an if statement before newNode->data if (newNodeIS != NULL) { if (newNodeIS->data > listHeadIS->data) { listHeadIS = newNodeIS; } } But I still get a segmentation fault.
Usually this kind of mistake is repeated throughout the entire code , try going over it and clean this specific bug , then run it again :)
0

first in the function createNode,u use the element "data" but didn't malloc a real memory for the newNodeCN whitch's type is struct ListNode. besides, the "segmentation fault" usually comes up when u attend to reference a wrong memory address(such as a pointer u not malloc, or a address out of a array and so on).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.