Simon February 2016

C linked list: Segmentation fault on Windows, works on Mac

I'm trying to go through a linked list in C.

A list item is defined as

struct list_element {
  struct list_element *next;
  int value;
};

The list head is defined as

struct list_head {
  struct list_element *front;
  struct list_element *end;
};

and I'm trying to print the items like this

void printList(struct list_head* head) {
    if(head == NULL|| head->front == NULL) {
        printf("List is empty \n");
        return 0;
    }

    struct list_element* elm = head-> front;
    int numberOfElements = 0;

    while(elm != NULL) {
        printf("%i", elm -> value);
        printf(" ");
        elm = elm -> next;
    }
    printf("\n");
}

This works perfect on my Mac in XCode and on https://ideone.com, but on Windows and http://codepad.org it results in "Segmentation fault". It seems like

while(elm != NULL) {
    printf("%i", elm -> value);
    printf(" ");
    elm = elm -> next;
}

causes some issues. It seems like elm doesn't point to NULL for the last item, even though it should.

I'm adding items like this

struct list_element* list_push(struct list_head* head) {

    //List head is null
    if(!head) {
        return NULL;
    }

    //Initialize list element

    struct list_element* elm = malloc(sizeof(struct list_element));

    if(elm == NULL) {
        //Couldn't alloc memory
        return NULL;
    }

    if(head->front) {
        head->front = elm;
        head->end = elm;
    } else {
        //List head is not null, set next elm to point to current elm
        elm -> next = head -> front;
        head->front = elm;

    }

    return elm;
}

And I'm seriously confused why the same code would work in some places but not in others. (It wo

Answers


Rabbid76 February 2016

You have to initialize ele->next with NULL for the first element of list, Otherwise you access to uninitialized memory in elm = elm->next for the last element of list. Apart from this you have to change if(head->front) to if ( head->front == NULL ). Adapt your code like this:

struct list_element* list_push(struct list_head* head) {

    if ( head == NULL )
        return NULL;

    struct list_element* elm = malloc(sizeof(struct list_element));
    if ( elm == NULL)
        return NULL;

    if ( head->front == NULL)  // <--------------
    {
        elm->next = NULL;     // <---------------
        head->front = elm;
        head->end = elm;
    }
    else
    {    
        elm->next   = head->front;
        head->front = elm;
    }
    return elm;
}

Make sure you initialized head->front an head->end with NULL.


Gavin February 2016

The problem is that malloc is not zeroing the memory allocated to it for you. You can either set the next pointer to NULL manually, or you can use calloc to allocate the memory, which will zero it for you. The reason it works in some environments and not others is that either it's hitting memory that was already written with zeros in some cases, or that some operating systems will zero out the memory for you for security reasons.

Post Status

Asked in February 2016
Viewed 2,296 times
Voted 10
Answered 2 times

Search




Leave an answer