Thread: Fields of a struct after freeing it - C

  1. #1
    Registered User
    Join Date
    Nov 2019
    Posts
    135

    Fields of a struct after freeing it - C

    Hey all.

    Suppose we have the following struct definition of Stack data structure implementation:

    Code:
    typedef struct StrStackLink {
       char* str;
       struct StrStackLink *next;
    } StrStackLink; 
    
    struct StrStack {
       StrStackLink* top;
    };
    Where its Pop method implementation is shown below:

    Code:
    char* StrStackPop(StrStack* stack)
    {
       char *s;
       StrStackLink *p;
       assert( stack != NULL );
       if (stack->top == NULL) {
          return NULL;
       }
       s = stack->top->str;
       p = stack->top; // This lives in the HEAP
       stack->top = p->next;
       free(p);
       return s;
    }
    My question is about the line:
    Code:
       s = stack->top->str;
    Why is it correct?
    After we free p struct (which is the former top), its str field is not "disappeared"?

    Thanks in advance!

  2. #2
    Registered User
    Join Date
    Dec 2017
    Posts
    1,633
    The string would've (most likely) been separately allocated, so it has it's own place in memory that is separate from the struct, which only contains a pointer to the string. So freeing the struct doesn't free the string.

    You take a copy of the pointer before freeing the struct so that you still have a reference to the string. If you didn't take a copy of the string pointer then you would lose the reference to the memory where the string is stored. That's called a "memory leak".

    Eventually the string itself should be freed (if it was dynamically allocated in the first place).
    A little inaccuracy saves tons of explanation. - H.H. Munro

  3. #3
    Registered User
    Join Date
    Nov 2019
    Posts
    135
    Quote Originally Posted by john.c View Post
    The string would've (most likely) been separately allocated, so it has it's own place in memory that is separate from the struct, which only contains a pointer to the string. So freeing the struct doesn't free the string.

    You take a copy of the pointer before freeing the struct so that you still have a reference to the string. If you didn't take a copy of the string pointer then you would lose the reference to the memory where the string is stored. That's called a "memory leak".

    Eventually the string itself should be freed (if it was dynamically allocated in the first place).
    That's the point - the string is not dynamically allocated. So, it shouldn't be freed.
    But, if it's not dynamically allocated - does this string still live after we free the struct he is a field of?

    Thank you!

  4. #4
    Registered User
    Join Date
    Dec 2017
    Posts
    1,633
    Quote Originally Posted by HelpMeC View Post
    if it's not dynamically allocated - does this string still live after we free the struct he is a field of?
    Yep. Why wouldn't it? If it's not dynamically allocated then free can't free it. It's either stored in an active stack frame or in the global memory space. The stack frame is deallocated when the function that allocated it returns. The global memory is deallocated when the program ends.
    A little inaccuracy saves tons of explanation. - H.H. Munro

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    You need to show us your StrStackPush() and how you call it.

    Because if you don't know where your strings are, chances are - you're doing it wrong.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    Registered User
    Join Date
    Nov 2019
    Posts
    135
    Quote Originally Posted by john.c View Post
    Yep. Why wouldn't it? If it's not dynamically allocated then free can't free it. It's either stored in an active stack frame or in the global memory space. The stack frame is deallocated when the function that allocated it returns. The global memory is deallocated when the program ends.
    Got it.
    Thank you!

  7. #7
    Registered User
    Join Date
    Nov 2019
    Posts
    135
    Quote Originally Posted by Salem View Post
    You need to show us your StrStackPush() and how you call it.

    Because if you don't know where your strings are, chances are - you're doing it wrong.
    So, in this particular example:

    Code:
    void StrStackPush(StrStack* stack, char* s) 
    {
       assert( stack != NULL );
       StrStackLink *p = (StrStackLink*)
                                  malloc(sizeof(StrStackLink));
       if (p == NULL)
       {
          printf("out of memory, cannot push a string to the
                  stack\n");
          return;
       }
       p->str = s;
       p->next = stack->top;
       stack->top = p;
    }

    Code:
    #include <stdlib.h>
    #include <stdio.h>
    #include "StrStack.h"
    char * readline() {  ... } //A function to read a line 
    int main() {
       char *line;
       StrStack *stack = StrStackNew(); 
       while ((line = readline()) != NULL)
       {
          StrStackPush(stack, line);
       }
       while ((line = StrStackPop(stack)) != NULL)
       {
          printf("%s\n", line);
          free(line);
       }
       StrStackFree(&stack); 
       return 0;
    }
    Where readline function returns a char pointer.

    So as john has described - our str's here live in the main stack frame, which is also in charge of creating new pointers to new chars (by readline) using the temporary line pointer.

    So, the pointer of each str lives as long as the main lives - which is until the end of the program.

  8. #8
    Registered User
    Join Date
    Dec 2017
    Posts
    1,633
    That's not quite right. Although the pointer lives on main's stack, the memory it points to is on the heap since it is (presumably) dynamically allocated by readline. Note that that memory is freed in main in the loop that pops the stack elements.
    A little inaccuracy saves tons of explanation. - H.H. Munro

  9. #9
    Registered User
    Join Date
    Nov 2019
    Posts
    135
    Quote Originally Posted by john.c View Post
    That's not quite right. Although the pointer lives on main's stack, the memory it points to is on the heap since it is (presumably) dynamically allocated by readline. Note that that memory is freed in main in the loop that pops the stack elements.
    Oh yea. So readline is allocating str's eventually in the HEAP - so we have nothing to fear at all when we free the struct.

    Thank you!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Sort fields in struct
    By telmo_d in forum C Programming
    Replies: 11
    Last Post: 05-16-2015, 12:28 PM
  2. declaring a struct with its fields as a struct
    By starmandell in forum C Programming
    Replies: 1
    Last Post: 03-29-2011, 06:54 AM
  3. Struct of bit fields.
    By Kempelen in forum C Programming
    Replies: 5
    Last Post: 06-21-2008, 02:36 PM
  4. union in struct with bit fields
    By sagarnewase in forum C Programming
    Replies: 4
    Last Post: 05-12-2008, 07:30 AM
  5. struct - bit fields
    By chubaka in forum C Programming
    Replies: 4
    Last Post: 02-01-2002, 07:37 PM

Tags for this Thread