Search code examples
cmemory-leaksnodesdynamic-memory-allocationfree

Understanding how freeing a head allocated pointer in structures work in C


So I have this NODE structure

typedef struct tNODE {
    struct tNODE* parent;
    char* tag;
}NODE;

and I have a free function that goes through all the nodes and frees them.

Also I have a new node function that simply mallocs the amount of a Node structure and sets everything to NULL except parent.

NODE* new_node(NODE* parent){
    NODE* result = malloc(sizeof(NODE));
   
    result->inner_text = NULL;
    result->parent = parent;
}   

My question is that if for example I have the following code

NODE* temp = new_node(parent);
temp->tag = "x"

and

NODE* temp = new_node(parent);
temp->tag = strdup("x");

I can free the strdup("x") version with free(temp->tag) but not the temp->tag = "x". so I have 2 Questions.

1-:Why is this happening ? isnt there a memmory allocated when the new_node function is called ?

2- If I have a code with the first version(that means temp->tag = "x") and I want to free all the nodes, Does that mean that I have to only call free(temp) and the tag will also get free'd ? Thank you


Solution

  • the abbreviated answer is that you cannot free the memory in case of the first example, the detailed reason is that:

    in case of the first version when you typed:

    NODE* temp = new_node(parent);
    temp->tag = "x";
    

    this created a null-terminated string stored in the read-only memory, not the heap memory, to be more specific in the .rodata section of the memory which is just a section of the memory where you can only read but not modify strings, so if you write a code like:

    NODE* temp = new_node(parent);
    temp->tag = "x";
    temp->tag[0] = 's';
    

    the line temp->tag[0] = 's'; will throw a segmentation error as you are trying to modify a memory that can't be modified, that's why they say that the strings are immutable, which means that in case of the first example code, you cannot free the memory pointed by the pointer because the "x" will always be there in the read-only memory at any time of the execution of the program.

    in the second case when you wrote:

    NODE* temp = new_node(parent);
    temp->tag = strdup("x");
    

    you can refer to strdup() manual where they said:

    The strdup() function returns a pointer to a new string which is a duplicate of the string s. Memory for the new string is obtained with malloc(3), and can be freed with free(3).

    which means that the "x" is stored in the heap memory which is modifiable and readable memory, so you can modify it and read it and free it at any time.