Reputation: 171
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
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
Reputation: 70929
As indicated here acessing a poitner after you free it is undefined behavior.
Upvotes: 0
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
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