Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Copying struct pointer element to a pointer seems to corrupt it

Tags:

c

I'm still learning C and I must have misunderstood pointers at some point.

I was under the impression that the following lines would copy the memory address stored by l->first to temp. They are both struct list_el* pointers, so I can't see the problem.

struct list_elt * temp;
temp = l->first;

Running my sample code gives me an infinite loop:

user@machine:~$ gcc question.c 
user@machine:~$ ./a.out | head
append(): l->first->val: 30, l->first->next == NULL: 1
main()  : l->first->val: 30, l->first->next == NULL: 1
print() : l->first->val: 30, l->first->next == NULL: 1
print() : temp->val: 30, temp->next == NULL: 0
print() : temp->val: 30, temp->next == NULL: 0
print() : temp->val: 30, temp->next == NULL: 0
print() : temp->val: 30, temp->next == NULL: 0
print() : temp->val: 30, temp->next == NULL: 0
print() : temp->val: 30, temp->next == NULL: 0
print() : temp->val: 30, temp->next == NULL: 0

Here's question.c. I'm sorry I couldn't narrow it down further, every time I do the problem seems to magically go away.

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

struct list_elt {
    int val;
    struct list_elt * next;
};
struct linked_list {
    struct list_elt* first;
};

void print(const struct linked_list * l);
struct linked_list* new_list(void);
void append(struct linked_list* l, int value);


main()
{
    struct linked_list * l;
    l = new_list();
    append(l, 30);
    printf("main()  : l->first->val: %d, l->first->next == NULL: %d\n", l->first->val, l->first->next == NULL);
    print(l);
}

struct linked_list* new_list()
{
    struct linked_list* l;
    l = (struct linked_list*) malloc(sizeof(struct linked_list));
    l->first = NULL;
    return l;
}

void append(struct linked_list* l, int value)
{
    struct list_elt el = {0, NULL};
    el.val = value;
    el.next = NULL;
    if (l->first == NULL) {
        l->first = (struct list_elt*) &el;
        printf("append(): l->first->val: %d, l->first->next == NULL: %d\n", l->first->val, l->first->next == NULL);
    } else {
        printf("append(): Unimplemented\n");
    }
}


void print(const struct linked_list * l)
{
    printf("print() : l->first->val: %d, l->first->next == NULL: %d\n", l->first->val, l->first->next == NULL);
    struct list_elt * temp;
    temp = l->first;
    while (temp != NULL) {
        printf("print() : temp->val: %d, temp->next == NULL: %d\n", temp->val, temp->next == NULL);
        temp = temp->next;
    }
    printf("\n");
}

Thanks.

like image 743
Flimm Avatar asked May 30 '11 15:05

Flimm


2 Answers

You are allocating your list_elt on the stack of the append function. this pointer is invalid once the function returns, and should no longer be referenced.

You should allocate your elements with malloc instead.

like image 79
Hasturkun Avatar answered Nov 14 '22 22:11

Hasturkun


In append(), you are setting l->first to the address of a local stack variable, el. But el goes out of scope as soon as append() returns, so any attempt to dereference l->first afterwards is undefined behaviour.

like image 40
Oliver Charlesworth Avatar answered Nov 14 '22 22:11

Oliver Charlesworth