Home > Back-end >  What happens to malloced data in a struct in C when it is assigned to another variable?
What happens to malloced data in a struct in C when it is assigned to another variable?

Time:04-08

Let's say I have a structure named "example" which has a member named data which stores data allocated on the heap:

typedef struct _EXAMPLE
{
    signed char *data;
    size_t size;
} example_t;

example_t *example_alloc(size_t size)
{
    example_t *ret = malloc(sizeof *ret);
    ret->size = size;
    ret->data = calloc(size, sizeof *ret->data);

    return ret;
}

example_t *a = example_alloc(10), b = *a;

Is the value in b.data stored on the stack or the heap? Does it point to the data in a?

CodePudding user response:

Pointers are just values.

In the same way that b.size is just a copy of a->size, b.data is a copy of the same pointer value that a->data holds.

It points to the same location, wherever that may be.

Care must be taken, as freeing a->data invalidates b.data, and vice versa, which may result in Undefined Behavior if accessed.

CodePudding user response:

The structure b is a local variable, and all its members are stored locally in the stack (please, no pedantic comments saying that C doesn't specify that there's a stack -- it requires something that acts like a stack).

Since b.data is a member of b, it's stored on the stack. However, the data that it points to is the same as what a->data points to, and that's the heap memory that was allocated with calloc() in the function.

CodePudding user response:

Following b = *a, a->data == b.data. That is to say they both refer to the same allocated memory. This is known as a "shallow copy". To achieve a "deep copy" in C would require additional code. For example:

example_t* example_copy( example_t* b, const example_t* a )
{
    *b = *a ; // shallow copy all members
    
    // Allocate new block and copy content
    size_t sizeof_block = b->size * sizeof(*b->data)
    b->data = malloc( sizeof_block ) ;
    memcpy( b->data, a->data, sizeof_block ) ;

    return &b ;
}

Then

example_t *a = example_alloc(10) ;
example_t b ;
example_copy( &b, a ) ;
  • Related