jelipito
jelipito

Reputation: 171

linked list behavior - help me understand

i am in the process of learning linked lists, and i dont understand the behavior change when freeing a string. Here is the code:

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

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

void Push(struct node** headRef, char *data)
{
    struct node* newNode = malloc(sizeof(struct node));
    newNode->data = data;
    newNode->next = *headRef;  // The '*' to dereferences back to the real head
    *headRef = newNode;        // ditto
}

int main(int argc, const char * argv[])
{

    char* auxStr;
    struct node* list;
    struct node* auxPtr;
    int i=5;


    while (i<9)
    {
        auxStr=malloc(sizeof("String:%d"));
        sprintf(auxStr, "String:%d",i);
        Push(&list, auxStr);
        i++;
    }

    auxPtr=list;

    i=0;
    while (auxPtr)
    {
        printf("Node:%d - Data:%s\n",i++,auxPtr->data);
        auxPtr=auxPtr->next;
    }

    return 0;
}

That results in:

Node:0 - Data:String:8
Node:1 - Data:String:7
Node:2 - Data:String:6
Node:3 - Data:String:5

now, when i add free(auxStr) in the first while:

while (i<9)
{
    auxStr=malloc(sizeof("String:%d"));
    sprintf(auxStr, "String:%d",i);
    Push(&list, auxStr);
    free(auxStr);
    i++;
}

i now get:

Node:0 - Data:String:8
Node:1 - Data:String:8
Node:2 - Data:String:8
Node:3 - Data:String:8

Can someone explain why ? i know it may not be the most efficient code freeing in there multiple times, but i saw this behavio and it is puzzling me. Would appreciate your help to help me understand the concept better.

Thanks

Upvotes: 1

Views: 128

Answers (4)

md5
md5

Reputation: 23699

Each of your data in struct node points on the same address. When freeing auxPtr, you are accessing to a memory location which is not allocated anymore. In C, it leads to an undefined behavior. It could be a better idea to dynamically allocate your data, as follow.

#include <assert.h>
#include <stdlib.h>
#include <string.h>

void Push(struct node **head, const char *data, size_t size)
{
  struct node *elt;

  elt = malloc(sizeof *elt);
  assert(elt != NULL);

  elt->data = malloc(size);
  assert(elt->data != NULL);
  memcpy(elt->data, data, size);

  elt->next = *head;
  *head = elt;
}

Moreover, there is no null pointer in your list. You should allocate list first.

Upvotes: 0

Ivaylo Strandjev
Ivaylo Strandjev

Reputation: 70929

As indicated here acessing a poitner after you free it is undefined behavior.

Upvotes: 0

kchoi
kchoi

Reputation: 525

You aren't copying the data string by strncpy - instead you are simply assigning pointer to the same string that you free later

Upvotes: 0

amit
amit

Reputation: 178451

You are getting undefined behavior.

You are freeing a memory (auxPtr) but you still happen to have a pointer to it - as the data in the relevant node. That is called a dangling reference.

What happens with this data is undefined, and it happens to be reusing the same address for each new allocation (but again, anything can happen).

Thus, when later printing the data - the output is undefined.

Upvotes: 2

Related Questions