Search code examples
cpointersstructdynamic-memory-allocation

Understanding dynamic memory allocation of a string within a struct


I have come across an instance where memory is allocated dynamically to a char pointer within a struct in a way that does not make much sense to me, but - of course - works. A similar question has been posted before. The answers, however, did not help me understand what is actually happening in the allocation process.

Here is the code example I found:

struct a_structure {
   char *str;
   struct a_structure *next;
};

Memory has been allocated in the following way:

ptr_start=(struct a_structure *)malloc(sizeof (struct a_structure *));
...
char *some_words="How does this work?";
ptr_start->str=(char *)malloc(strlen(some_words)+1);
strcpy(ptr_start->str, some_words);
ptr_start->next=(struct a_structure *)malloc(sizeof(struct a_structure *));
...

I don't understand why malloc is used with the size of a pointer here. ptr_start is a pointer of type struct a_structure. That would mean it needs memory of size sizeof(struct a_structure) + the size of my string that hasn't been specified in the structure declaration. In the above example, however, malloc returns the address of yet another pointer pointing to a structure of type a_structure, am I right?


Solution

  • I don't understand why malloc is used with the size of a pointer here. ptr_start is a pointer of type struct a_structure. That would mean it needs memory of size sizeof(struct a_structure) + the size of my string that hasn't been specified in the structure declaration

    You are right. To create structure a_structure in order to manipulate it we need to allocate memory for whole structure. (Unless the object has been ALREADY created and for whatever reason we need a dynamically allocated pointer holding pointer to that object).

    but - of course - works.

    The presented fragment of the program cannot work properly for the stated above reasons.

    In the above example, however, malloc returns the address of yet another pointer pointing to a structure of type a_structure, am I right?

    Yes, you are right.

    This is also problematic:

    ptr_start->next=(struct a_structure *)malloc(sizeof(struct a_structure *));

    ptr_start->next can hold a pointer already. We typically do not need to allocate a pointer here. We would assign a pointer to the existing structure or we would allocate memory for the whole structure.

    See example:

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    
    struct a_structure {
       char *str;
       struct a_structure *next;
    };
    
    struct a_structure * allocatePointer(void)
    {
        // ptr ptrToObj1Allocated points to allocted memory which can hold a ponter   
        struct a_structure * ptrToObj1Allocated = malloc(sizeof (struct a_structure *)); 
        return ptrToObj1Allocated;
    }
    
    int main(){       
        // 1.
        struct a_structure obj1;    //  structure a_structure has been allocated on the stack 
    
        struct a_structure * ptrToObj1 = & obj1; // points to the existing structure
    
        char *some_words = "How does this work?";
        ptrToObj1->str = malloc(strlen(some_words)+1);
        if(ptrToObj1->str == NULL){printf("No enough memory\n"); return -1;}
    
        strcpy(ptrToObj1->str, some_words); // copy the string
        // now obj1 has its own copy of the string.
    
        // 2.
        // dynamically allocate another structure on the heap
        // we want to allocate memory for the structure not just a memory to keep the pointer to the structure.
    
        struct a_structure *obj2 = malloc( sizeof (struct a_structure));  // memory has been allocated to hold struct a_structure with 2 pointers
        if(obj2 == NULL){printf("No enough memory\n"); return -2;}
    
        char *words = "More words..";
        obj2->str = malloc(strlen(words)+1);
        if(obj2->str == NULL){printf("No enough memory\n"); return -3;}
    
        strcpy(obj2->str, words);  // copy the string
    
        obj2->next = ptrToObj1;    // points to the already existing object
    
         //----
        printf("String in obj1 is: %s\n", ptrToObj1->str);
        printf("String in obj2 is: %s\n", obj2->str);          
        printf("obj2->next points to structure with string: %s\n", obj2->next->str );  
    
        // free the allocated  memory:   
        free(ptrToObj1->str);
    
        free(obj2->str);     
        free(obj2);    
    
        return 0;
    }
    

    Output:

    String in obj1 is: How does this work?
    String in obj2 is: More words..
    obj2->next points to structure with string: How does this work?