During my experience with C coding, I've seen 2 ways of passing arguments for functions:
malloc
before calling functions
malloc
inside functions (variable is not initialized before calling function)
I, particularly, prefer the second form. But while I'm the only one to code my program, I know that, but some else could not know, and could lead to 2 malloc
, and leak of memory.
So, my question is: What's the best practice for this?
In C, the library function malloc is used to allocate a block of memory on the heap. The program accesses this block of memory via a pointer that malloc returns. When the memory is no longer needed, the pointer is passed to free which deallocates the memory so that it can be used for other purposes.
To malloc inside a function, process the code, and then return the pointer to that heap space. To malloc outside of a function, i.e. within main(), and passing that pointer to a void function for processing.
Syntax of calloc() Function: After the memory space is allocated, then all the bytes are initialized to zero. The pointer which is currently at the first byte of the allocated memory space is returned.
Calloc is slower than malloc. Malloc is faster than calloc. It is not secure as compare to calloc. It is secure to use compared to malloc.
Allocating memory in the caller is more flexible, because it allows the caller to use static or automatic storage instead of dynamic allocation, and eliminates the need to handle the case of allocation failure in the callee. On the other hand, having the caller provide the storage requires the caller to know the size in advance. If the size is compiled into the caller as a constant and the callee is in a library that's later updated to use a larger structure, things will break horribly. You can avoid this, of course, by providing a second function (or external variable in the library) for retrieving the necessary size.
When in doubt, you can always make two functions:
Then the caller is free to choose whichever method is more appropriate for the particular usage case.
I personally strongly favor your first proposition (whenever it is possible) for orthogonality. Take the following example:
extern void bar(int *p, int n);
void foo(int n)
{
int *p = malloc(n * sizeof *p);
// fill array object
bar(p, n);
// work with array elements
/* ... */
// array no longer needed, free object
free(p);
}
This is orthogonal. malloc
and free
are called in the same lexical scope which is clean and readable. Another advantage is you can pass to bar
function an array with a different storage duration for example an array with automatic or static storage duration. You let bar
function focus only on the work it has do and let another function manage the array allocation.
Note that this is also how all Standard C functions work: they never appear to call malloc
.
The criteria I'd use for deciding are:
If the code outside the called function can know how much memory to allocate, then it is better to have the calling code allocate the memory.
If the code outside the called function cannot know how much memory to allocate, then the called function must do the memory allocation. It is likely then that there will be a second function available to release the memory returned by the first function (the 'called' function), unless it is just a single free()
that's needed. The function documentation should make this clear.
For example, if the called function is reading a complete tree structure from a file, the function will have to allocate the memory. But, there will also be a companion function for releasing the memory (since the called code knows how to do it and the calling code shouldn't need to know).
On the other hand, if the called function is reading a simple list of integer and floating point values into a fixed size structure, it is far better to make the calling function allocate the memory. Note that I skipped 'strings'! If the strings are of a fixed size in the structure, then the calling function can do the allocation, but if the strings are of variable size, then probably the called function does the allocation.
The Standard C Library has functions like fgets()
which expect the calling code to allocate the memory to be used. The calling sequence tells fgets()
how much space is available. You run into problems if you didn't provide enough memory. (The problem with fgets()
is that you may only get the start of a line of text, not the whole line of text.)
The POSIX 2008 Library provides getline()
which will allocate enough space for the line.
The asprintf()
and related functions (see TR24731-2) allocate memory as required. The snprintf()
function does not — it is told how much space there is available, it uses no more than that, and says how much it really needed, and it is up to you to note if you didn't provide enough space and do something about it (allocate more space and try again, or blithely ignore the truncated value and continue as if nothing went wrong).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With