Reputation: 487
I have a function which populates dynamic arrays based on contents of a binary file.
I am using malloc
to size the array of strings inside the function, then return the pointer and size information back to the calling function. Since it is an array of strings I am using an array of pointers, so calling malloc
for the array pointer, then malloc
for each member.
i.e. in my function I have this code block. The function returns p_count
and p_tokens
to the caller.
// Allocate memory:
*p_tokens = malloc(*p_count * sizeof(char *));
for (int i = 0; i < (int)*p_count; i++) {
(*p_tokens)[i] = malloc(TOKEN_LENGTH);
}
This makes use of free
from calling code necessary, but of course gets a bit messy. What is the best way to handle this scenario? Should I make a separate function to free all pointers generated within my original function? Should I just deal with a cluster of free loops at the end of my calling code, or am I going about the whole thing incorrectly?
Upvotes: 1
Views: 97
Reputation: 145
Ideally you should control the status of your "strings" somewhere. Structure of: pointers + flags for existence + flags for initialization + flags for access.
struct arrstring {
p_string * Strings;
// flags of allocation
p_exist * ExistFlag;
// flags tracking initialization with values
p_init * InitStrings;
// flags allowing access/lock
p_access * AccessF;
p_mutex * LockStrings;
}
This way you could create all strings with one call to 'calloc()', but initialize them later.
PS.
Here at sizeof(char *) you take size of pointer, I don't know your intentions but this looks like a misunderstanding. You can take ahead the maximum size of your string like 512 byte, and allocate it with malloc(MAX_SIZE*sizeof(char)).
Also using 'char' for strings is kind of deprecated feature. Good for testing purposes, but there is actual characters today, and 'char' is used as only acronym of 'byte' (it works because UTF-8 is widely accepted and smallest UTF-8 sized values picked coincidentally with ASCII).
PS2. The C17 standard is confirming that "uchar.h" and "wchar.h" are widely accepted and supported by C environments. So users could deal with characters accordingly if it goes beyond 'char' type.
PS3. Well, about the C standards about characters. C always were "silent" when it comes to characters and various systems decide it differently. So the way how C works with strings is named as "C strings" to distinguish it. In "C strings" the length of strings is always measured in "char" or "wchar_t" which are fixed size, even if the string itself is variable-width encoded, this could lead to problems because long width characters will be interpreted as few characters. But the size of "char" will always be fixed itself, on some machines it was 6 bit, on some machines it was 12 bit. Now it is mostly 8 bit, so most of the times programmers are referring to it as "integer type", and there is common ground when programmers suppose that char=byte. Well it reflects by itself the evolution of term of "byte" itself.
Upvotes: 0
Reputation: 144780
Writing a free_token_array(token *array, size_t count)
that would free the tokens and the array in the same module as your allocation function makes sense. This way you can easily keep them in sync if you change allocation strategies.
Also note that you should avoid casting *p_count
in the allocation loop, just write:
for (size_t i = 0; i < *p_count; i++)
Upvotes: 2
Reputation: 11791
You must make sure the malloc()
s are paired with the free()
s. Where you write them is quite irrelevant, the really important point is that the code is structured so that it is easy to check (i.e., hard(er) to get wrong) that they do balance. For example, around the idea of "create (and allocate), use, consume (and free)".
Look for debugging packages, there are instrumented libraries that check specifically for memory management bugs.
Another way to handle this (at some performance cost) is to use some garbage collecting library, like the Boehm garbage collector for C and C++ (a detailed example is given in "Garbage Collection in C Programs" by Insolvible,Linux Journal, aug 2003). The garbage collector is available on most Linux distributions, being open source it can be built and installed on most systems.
Upvotes: 2