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!
CodePudding user response:
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.
CodePudding user response:
Both implementation are good, the first one uses heap memory by calling malloc()
once which means you need to free()
only once.
Whereas, in the second implementation, it uses heap memory by calling malloc()
twice, so you need to call free()
twice, which leads to additional calls to free()
later in your code.
NOTE: Number of calls to malloc()
should be equal to number of calls to free()
. But in modern operating systems, sometimes freeing the heap allocated resources isn't needed, OS manage them accordingly.
CodePudding user response:
The second one.
The first one assumes its contiguous. The buffer for the struct is one buffer. This example has only one struct element which is a pointer. What happens if there is a second struct element? Say you have two pointers, they are allocated and free'd multiple times, do you think each time they will be to the same contigous region of memory? I don't think so.
Lastly, if you free the one and only item in your simple one item struct, you can no longer free the struct itself.