0

I have the following C program. It works when I include the following line, otherwise it gives a segmentation fault:

printf("head(%p), last(%p), newnode(%p)\n", head, last, newnode);

Any idea what's the issue here?

Here is my whole program. It's a basic circular queue example.

#include "stdio.h"
#include "malloc.h"

struct node {
    int data;
   struct node *next;
};

typedef struct node NODE;

void display(NODE *);

int main(void) {

    NODE *head, *last, *newnode = NULL;
    int i = 5;

    for ( ; i > 0; i--) {
        newnode = (NODE *) malloc(sizeof(NODE));
        newnode->data = i*10;
        newnode->next = NULL;

        //printf("head(%p), last(%p), newnode(%p)\n", head, last, newnode);


        if (head == NULL) {
            head = newnode;
            last = newnode;
        } else {
           last->next = newnode;
           last = newnode;
        }

        last->next = head;
    }

    display(head);

    return 1;
}

void display(NODE *head) {

    NODE *temp = NULL;
    temp = head;

    printf("Elements --> ");
    do {
            printf("%d ", temp->data);
            temp = temp->next;
    } while (temp != head);

    printf("\n");

}

3 Answers 3

7

You need to explicitly initialize head and last to NULL also.

In your declaration:

NODE *head, *last, *newnode = NULL;

only newnode is being initialized to NULL. Consequently later in your if/else you're testing/assigning to random memory.

Do something like this:

NODE *head, *last, *newnode;
head = last = newnode = NULL;

You can't assume that pointers are automatically initialized to NULL, even though it may be the case on certain systems. Variables declared as static are an exception. Always initialize variables in C to reasonable values, especially pointers.

When you access garbage memory you're invoking undefined behavior. When you do this you may observe inconsistent and confusing results. In your case, adding the printf seemed to fix the problem. The reason that this affected the behavior of your code is implementation dependent and - once you've introduced undefined behavior - beyond your control.

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

5 Comments

Thanks. It worked perfectly fine. Can you explain why was the segmentation fault without the printf() statement and with it it worked fine. Also, I think when we declare a pointer, it automatically assigned to NULL. Is that not true?
@divinedragon: A pointer variable will have the value NULL at program start if and only if the variable is global (this includes static variables). Local variables take an "indeterminate value" instead. There is no reason it worked with printf, there is only coincidence.
@divinedragon - Several years ago I was amazed that an uninitialized pointer made it for years in a released product without ever causing a problem, until something else unrelated to that pointer was changed, exposing the uninitialized pointer bug. Out of dumbfounded curiosity, I dumped a disassembly of the old ("working") version of the code and traced backwards, discovering that the same stack location was used at one time for the local pointer variable, and at an earlier point (IN A DIFFERENT FUNCTION) as something else, which was always zero (i.e. "NULL") when exiting that function.
...and when the code was modified, those two entities (the uninitialized pointer and the other variable that was always zero upon exiting the earlier function) no longer lined up to the same stack location, exposing the bug.
@divinedragon What's happening is that your program is still wrong with the printf statement; you're just getting lucky. Just because it doesn't segfault doesn't mean the code is 100% correct. As people have implicitly pointed out, pointers do not get automatically assigned to NULL.
3

last and head are not being initialized. You can turn on compiler warnings that will help you out:

$ gcc -O1 -Wall w.c -o we
w.c: In function ‘main’:
w.c:30:23: warning: ‘last’ may be used uninitialized in this function [-Wuninitialized]
w.c:26:12: warning: ‘head’ may be used uninitialized in this function [-Wuninitialized]

(Note that gcc needs -O1 for -Wuninitialized to work.)

1 Comment

Thanks. It worked perfectly fine. Can you explain why was the segmentation fault without the printf() statement and with it it worked fine. Also, I think when we declare a pointer, it automatically assigned to NULL. Is that not true?
2

You're not initialising head and last,

NODE *head, *last, *newnode = NULL;

so they have whatever garbage bits are where they are allocated and if (head == NULL) can fail even though head is not properly set. Initialise them to NULL too.

2 Comments

Thanks. It worked perfectly fine. Can you explain why was the segmentation fault without the printf() statement and with it it worked fine. Also, I think when we declare a pointer, it automatically assigned to NULL. Is that not true?
Only static variables are initialised automatically. Your pointers are automatic variables, so they're not initialised. As for why printf averted the crash, I can't tell, it's undefined behaviour.

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.