0

Hi I have a struct like this

struct small_struct {
  int a;
  int b;
}

struct big_struct {
  struct *small_struct child;
}

I want to pass the pointer of big_struct as a parameter into a function in which child is initialized.

static int my_function(struct big_struct* s) {
  if (certain_condition)
    s->child = &(struct small_struct) {
      .a = 1;
      .b = 2;
    }
}

However, when I do this and my_function is finished, the fields in s->child are often changed outside of the my_function. Would there be a way to keep a and b values as it was initialized inside my_function?

Thank you!

5
  • 4
    When you use a compound literal inside a function, the lifetime of the data ends when the function returns. You need to use malloc() to allocate the memory dynamically. Commented Mar 2, 2022 at 23:57
  • 1
    It looks like you're dynamically allocating a new instance of "struct small_struct" on the stack inside of my_function(). That instance is no longer valid once my_function() exits. Two workarounds are 1) malloc() small_struct, or 2) declare small_struct inside of big_struct (instead of defining child as "struct small_struct *", declare child as ""struct small_struct". Commented Mar 3, 2022 at 0:01
  • 1
    Is there a reason that child has to be a pointer, instead of an instance of small_struct? Commented Mar 3, 2022 at 0:26
  • The best solution is indeed to include the small struct as a member variable of the big struct, rather than as a pointer. Commented Mar 3, 2022 at 11:17
  • @Barmar, nitpicking, the lifetime of a compound literal ends when the block containing it ends. Commented Mar 3, 2022 at 11:54

1 Answer 1

3

The problem is here:

s->child = &(struct small_struct) {
  .a = 1;
  .b = 2;
}

This creates the struct in the stack memory of the function, then assigns the s->child pointer to that memory. As soon as the function returns, that memory is no longer allocated to your struct. What you need to do is allocate heap memory for the structure, using malloc, which will stay allocated until it is free'd with a call to free:

static int my_function(struct big_struct* s) {
if (certain_condition)
{
    //Allocate *heap* memory for the pointer
    //This must be freed later!
    //e.g free(s.child);
    s->child = malloc(sizeof(struct small_struct));
    s->child->a = 1;
    s->child->b = 2;
}

Alternatively, depending on what you are trying to do, don't make child a pointer, that way the memory is already allocated in the instance of big_struct e.g.:

struct big_struct 
{
  struct small_struct child; //Note: not a pointer
};

static int my_function(struct big_struct* s) {
  if (certain_condition)
  {
    //Memory for child member is already allocated
    s->child.a = 1;
    s->child.b = 2;
  }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you. This is exactly what user3386109 and I were trying to tell the OP. With an excellent example/explanation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.