Search code examples
cstructreturn-valuedynamic-memory-allocation

Returning dynamic memory inside a struct in C


Hi I have the following struct

typedef struct mystruct_s {
    int* array;
} mystruct;

and I want to create a function that initializes it. I have two ways of doing it.

First one is:

mystruct new_mystruct()
{
    mystruct tmp;
    tmp.array = malloc(sizeof(int) * 5);

    return tmp;
}

Second one is:

mystruct* new_mystruct()
{
    mystruct* tmp = malloc(sizeof(mystruct));
    tmp->array = malloc(sizeof(int) * 5);

    return tmp;
}

I want to know which one is the better approach.

Thanks in advance!


Solution

  • A general rule of thumb is to never pass structs by value, mainly for performance reasons. The first version should be avoided for that reason.

    Regarding the second version, then there's some more advanced issues. Multiple calls to malloc() have the following problems:

    • Each call comes with execution overhead of its own.
    • Each call may give a different segment, causing heap segmentation over time = poor usage of memory.
    • Allocations in different segments means poor utilization of data cache on CPUs that support it.
    • You need to make multiple calls to free() as well. Again extra execution overhead and the potential of memory leaks if you don't call it multiple times.

    A better method is to use flexible array members:

    typedef struct {
      size_t size
      int array[];
    } mystruct;
    
    size_t n = 123;
    mystruct* ms = malloc( sizeof *ms + sizeof(int[n]) );
    ms->size = n;
    memcpy(ms->array, data, sizeof(int[n]));
    ...
    free(ms);
    

    This is faster and less complex all at once.