Is it bad practice to hide memory allocations in functions? - c

Should I expect the user to provide a memory chunk of sufficient size, say, for copying a file into a buffer? Or should I allocate the memory myself, and expect the user to free it when they're done? For example, the function strdup() allocates memory itself, but the function fread() expects only a buffer of sufficient size.

It depends - I've seen C APIs use all kind of patterns for this, such as:
functions that require the buffer and buffer size to be provided, and return the required size (so that you can adjust the buffer size if it was truncated); many of these allow passing NULL as a buffer if you are just asking how big the buffer should be; this allows the caller to use an existing buffer or to allocate an appropriately sized one, although with two calls;
separate functions to obtain needed size and to fill the buffer; same as above, but with a clearer interface;
functions that require buffer and buffer size, but can allocate the buffer themselves if NULL is passed as buffer; maximum flexibility and terseness, but the function signature can get confusing;
functions that just return a newly allocated string; simple to use and avoids bugs arising from unguarded truncation, but inflexible if performance is a concern; also, requires the caller to remember to free the returned value, which is avoided in the cases above if using a stack-allocated buffer;
functions that return a pointer to a static buffer, and then the caller is responsible to do whatever with it; extremely easy to use, extremely easy to misuse; requires care in case of multithreading (needs thread local storage) and if reentrancy is a concern.
The last one is generally a bad idea - it poses problems with reentrancy and thread safety; the one before it can be used but may pose efficiency problems - I generally don't want to waste time in allocations if I have already a buffer big enough. All the others are generally pretty much OK.
But besides the specifics of the interface, the most important point if you allocate stuff and/or return pointers is to clearly document who owns the pointed memory - is it a static object in your library? Is it a pointer to some internal of an object provided by the caller? Is it dynamically allocated stuff? Is the caller responsible for freeing it? Is it just the buffer that was provided as argument?
Most importantly, in case you allocated stuff, always specify how to deallocate it; notice that, if you are building a library that may be compiled as a dll/so, it's a good idea to provide your own deallocation function (even if it's just a wrapper around free) to avoid mismatches between different versions of the C runtime running in the same process. Also, it avoids tying your code to the C library allocator - today it may be fine, tomorrow it may turn out that using a custom allocator may be a better idea.

Is it bad practice to hide memory allocations in functions?
Sometimes.
An answer to show when code can be abused to detail one of the pitfalls of allowing a function total freedom in memory allocation.
A classic case occurs when the function itself determines the size needed, so the calling code lacks the information needed to to provide the memory buffer beforehand.
This is the case with getline() where the stream content throttles the size of the allocation. The problem with this, especially when the stream is stdin, is that the control over memory allocation is given to external sources and not limited by the calling code - the program. External input may overwhelm memory space - a hack.
With a modified function, such as ssize_t getline_limit(char **lineptr, size_t *n, FILE *stream, size_t limit);, the function could still provide a right-size allocation, yet still prevent a hacker abuse.
#define LIMIT 1000000
char *line = NULL;
size_t len = 0;
ssize_t nread;
while ((nread = getline_limit(&line, &len, stdin, LIMIT)) != -1) {
An example where this is not an issue would be an allocation with a well bounded use.
// Convert `double` to its decimal character representation allocating a right-size buffer
// At worst a few thousand characters
char *double_to_string_exact_alloc(int x)
Functions that perform memory allocation need some level of control to prevent unlimited memory allocation either with a specific parameter or by nature of the task.

C library functions refrain from returning allocated memory. That's at least part of the reason why strdup is not part of the standard library, along with a popular scanf extension for reading C strings of unlimited length.
Your library could choose either way. Using pre-allocated buffers is more flexible, because it lets users pass you statically allocated buffers. This flexibility comes at a cost, because user's code becomes more verbose.
If you choose to allocate memory for a custom struct dynamically, it is a good idea to make a matching function for deallocating the struct once it becomes unnecessary to the user.

Related

Is there a way to either query what would realloc do, or prevent it from copying all memory on Windows and Linux?

I'm implementing a container similar to std::vector from C++. It has a buffer with associated capacity (memory which is reserved for this container) and size (actual size of the container).
When the user adds elements and size needs to exceed the capacity, I use realloc for the new capacity.
There is a reserve function for the container which sets the capacity in case the user knows it beforehand and doesn't want to risk allocating memory when filling the container with data.
Thus invariants might exist where the size is small (say zero) and the capacity is big (say 1MB). Then if the user calls reserve(even_bigger_capacity), what am I supposed to do?
I can just call realloc, but if realloc does end up allocating a new memory block, it will copy 1MB of useless bytes into it.
I can have a constant: WASTEFUL_COPY_BYTES and check capacity - size > WASTEFUL_COPY_BYTES, and manually call malloc and memcpy and copy only what's needed, in case it's true, and only call realloc if the difference is small, but in this case I'm missing opportunities to use realloc where it would return the same address.
Basically I need something like bool try_realloc(void *old_addr, size_t new_size) which would return true if realloc would return the same address, but won't try to allocate a new block and copy stuff.
...or something like void* part_realloc(void* old_addr, size_t new_size, size_t relevant_size) which would only copy relevant_size bytes into the new block, if it ends up allocating one.
I'm sure there are platform-specific ways of implementing both of these functions, so my question is: is there a library with such functions which works on major platforms or, if not, how would I go about implementing something like this at least for Windows and Linux?
So, on Windows, _expand is exactly what I need.
On Linux, things don't look as simple. I'll need to deep dive in glibc. Perhaps malloc_usable_size will be helpful.
edit: It's not (well not very much. It returns too few bytes more than the allocation size). It seems there is no way to implement this with glibc's public interface. The only way is to look through glibc's code, duplicate the data structures and use the chunk before the returned memory block, which is a Bad Idea™
I'll report further findings here unless someone provides a better answer in the meantime

Best practice for allocating memory for use by a function — malloc inside or outside?

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?
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:
The main function that uses caller-provided storage.
A wrapper function which allocates the right amount of storage, calls the function in #1 using it, and returns the pointer to the caller.
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).
The principal of information hiding suggests that it allocating memory is best done within a function.
If you look at how stdio.h works:
FILE *myFile;
myFile = fopen("input.txt", "r");
if (!myFile) {
fprintf(stderr, "Error opening input.txt for reading.\n");
// other exit handling close
}
else {
// code to read from file
fclose(myFile);
}
the library call allocates memory that holds information about the file you are working with, and it returns a pointer to that structure. The caller is responsible for later on freeing that memory (with a call to fclose).
This pattern is repeated throughout the Standard C library.
There are at least two disadvantages to requiring the caller to allocate and free memory:
Extra code would be required on the calling side.
The calling code would need to be recompiled (at a minimum) or changed if the size of structure being allocated ever changed.

How to find how much memory is actually used up by a malloc call?

If I call:
char *myChar = (char *)malloc(sizeof(char));
I am likely to be using more than 1 byte of memory, because malloc is likely to be using some memory on its own to keep track of free blocks in the heap, and it may effectively cost me some memory by always aligning allocations along certain boundaries.
My question is: Is there a way to find out how much memory is really used up by a particular malloc call, including the effective cost of alignment, and the overhead used by malloc/free?
Just to be clear, I am not asking to find out how much memory a pointer points to after a call to malloc. Rather, I am debugging a program that uses a great deal of memory, and I want to be aware of which parts of the code are allocating how much memory. I'd like to be able to have internal memory accounting that very closely matches the numbers reported by top. Ideally, I'd like to be able to do this programmatically on a per-malloc-call basis, as opposed to getting a summary at a checkpoint.
There isn't a portable solution to this, however there may be operating-system specific solutions for the environments you're interested in.
For example, with glibc on Linux, you can use the mallinfo() function from <malloc.h> which returns a struct mallinfo. The uordblks and hblkhd members of this structure contains the dynamically allocated address space used by the program including book-keeping overhead - if you take the difference of this before and after each malloc() call, you will know the amount of space used by that call. (The overhead is not necessarily constant for every call to malloc()).
Using your example:
char *myChar;
size_t s = sizeof(char);
struct mallinfo before, after;
int mused;
before = mallinfo();
myChar = malloc(s);
after = mallinfo();
mused = (after.uordblks - before.uordblks) + (after.hblkhd - before.hblkhd);
printf("Requested size %zu, used space %d, overhead %zu\n", s, mused, mused - s);
Really though, the overhead is likely to be pretty minor unless you are making a very very high number of very small allocations, which is a bad idea anyway.
It really depends on the implementation. You should really use some memory debugger. On Linux Valgrind's Massif tool can be useful. There are memory debugging libraries like dmalloc, ...
That said, typical overhead:
1 int for storing size + flags of this block.
possibly 1 int for storing size of previous/next block, to assist in coallescing blocks.
2 pointers, but these may only be used in free()'d blocks, being reused for application storage in allocated blocks.
Alignment to an approppriate type, e.g: double.
-1 int (yes, that's a minus) of the next/previous chunk's field containing our size if we are an allocated block, since we cannot be coallesced until we're freed.
So, a minimum size can be 16 to 24 bytes. and minimum overhead can be 4 bytes.
But you could also satisfy every allocation via mapping memory pages (typically 4Kb), which would mean overhead for smaller allocations would be huge. I think OpenBSD does this.
There is nothing defined in the C library to query the total amount of physical memory used by a malloc() call. The amount of memory allocated is controlled by whatever memory manager is hooked up behind the scenes that malloc() calls into. That memory manager can allocate as much extra memory as it deemes necessary for its internal tracking purposes, on top of whatever extra memory the OS itself requires. When you call free(), it accesses the memory manager, which knows how to access that extra memory so it all gets released properly, but there is no way for you to know how much memory that involves. If you need that much fine detail, then you need to write your own memory manager.
If you do use valgrind/Massif, there's an option to show either the malloc value or the top value, which differ a LOT in my experience. Here's an excerpt from the Valgrind manual http://valgrind.org/docs/manual/ms-manual.html :
...However, if you wish to measure all the memory used by your program,
you can use the --pages-as-heap=yes. When this option is enabled,
Massif's normal heap block profiling is replaced by lower-level page
profiling. Every page allocated via mmap and similar system calls is
treated as a distinct block. This means that code, data and BSS
segments are all measured, as they are just memory pages. Even the
stack is measured...

Freeing all malloc()-created pointers with one command?

Is there a one-liner that will free the memory that is being taken by all pointers you created using mallocs? Or can this only be done manually by freeing every pointer separately?
you could do that by creating some kind of "wrapper" around malloc.
(warning that's only pseudo code showing the idea, there is no checking at all)
void* your_malloc(size_t size)
{
void* ptr = malloc(size);
// add ptr to a list of allocated ptrs here
return ptr;
}
void your_free(void *pointer)
{
for each pointer in your list
{
free( ptr_in_your_list );
}
}
But it doesn't sound like a good idea and I would certainly not do that, at least for general purpose allocation / deallocation. You'd better allocate and free memory responsibly when it is no longer needed.
You might want to look into memory pools. These are data structures built to do exactly this.
One common implementation is in the Apache Portable Runtime, which is used in the Apache web server, as well as other projects, such as Subversion.
malloc on it's own has implementation-defined behavior. So there isn't a necessity for it to keep track of all the pointers it has, which obviously puts a damper on the idea.
You'd need to make your own memory manager that tracks the pointers, and then provides a function called free_all or something that goes through the list of pointers it has and calls free on them.
Note, this sounds like a somewhat bad idea. It's better to be a bit more strict/responsible about your memory usage, and free things when you're done; not leave them hanging about.
Perhaps with a bit more background on where you want to apply your idea, we might find easier solutions.
Check out dlmalloc
ftp://g.oswego.edu/pub/misc/malloc.h
look at the following functions
/*
mspace is an opaque type representing an independent
region of space that supports mspace_malloc, etc.
*/
typedef void* mspace;
/*
create_mspace creates and returns a new independent space with the
given initial capacity, or, if 0, the default granularity size. It
returns null if there is no system memory available to create the
space. If argument locked is non-zero, the space uses a separate
lock to control access. The capacity of the space will grow
dynamically as needed to service mspace_malloc requests. You can
control the sizes of incremental increases of this space by
compiling with a different DEFAULT_GRANULARITY or dynamically
setting with mallopt(M_GRANULARITY, value).
*/
mspace create_mspace(size_t capacity, int locked);
/*
destroy_mspace destroys the given space, and attempts to return all
of its memory back to the system, returning the total number of
bytes freed. After destruction, the results of access to all memory
used by the space become undefined.
*/
size_t destroy_mspace(mspace msp);
...
/*
The following operate identically to their malloc counterparts
but operate only for the given mspace argument
*/
void* mspace_malloc(mspace msp, size_t bytes);
void mspace_free(mspace msp, void* mem);
void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size);
void* mspace_realloc(mspace msp, void* mem, size_t newsize);
You might want to do something called "arena allocation", where you allocate certain requests from a common "arena" which can be freed all at once when you're done.
If you're on Windows, you can use HeapCreate to create an arena, HeapAlloc to get memory from the heap/arena you just created, and HeapDestroy to free it all at once.
Note that when your program exit()s, all the memory you allocated with malloc() is freed.
Yes, you can do that unless you write your own defintion of malloc() and free(). You should probably call myCustomMalloc() instead of regular malloc() and you should be keeping track of all the pointers in some memory location and when you call the myCustomFree() method, you should be able to clear all the pointers that was created using your myCustomMalloc(). Note: both your custom methods will be calling malloc() and free() internally
By this way you can achieve your goal. I am a java person but I use to work a lot in C in my early days. I assume that you're trying to achieve a common solution where memory is being handled by the compiler. That has a cost of performance as it is seen in Java. You dont have to worry about allocation and freeing the memory. But that has a severe effect on performance. Its a tradeoff that you have to live with.

API design - allocate output?

Is it a good idea for C API functions to allocate their output, or to have the user specify the output buffer? For example:
BOOL GetString(
PWSTR *String
);
...
PWSTR string;
GetString(&string);
Free(string);
vs
BOOL GetString(
PWSTR Buffer,
ULONG BufferSize,
PULONG RequiredBufferSize
);
...
// A lot more code than in the first case
More specifically I'm wondering why the Win32 API primarily uses the second case (e.g. GetWindowText, LookupAccountSid). If an API function knows how big the output is, why have the user try to guess the output size? I can't find any information on why the second case would be used.
Also: the LookupAccountSid example is particularly bad. Internally it uses the LSA API, which allocates the output for the caller. Then LookupAccountSid gets the user to allocate a buffer (and guess the correct buffer size) when it could just return the output from LSA! Why?
The Win32 API does not pre-allocate buffers because it wants to give the calling code the choice of how to provide the buffer. It allows for them to provide stack and a variety of heap based buffers. There are several places where the maximum size of the buffer is known ahead of time and developers want the simplicity of using a stack based buffer.
The file system is the best example as paths won't exceed MAX_PATH. So rather than allocate + free. The developer simply declares a stack based buffer.
The advantage to having the C API allocate memory is that it simplifies the calling pattern. The downside of the Win32 pattern is that most times you end up calling the API twice. The first time to determine the size of the buffer, then the second time with a buffer of appropriate size. With an API allocated buffer only one call is needed.
The downside though is that you take away the choice of allocation from the caller. Additionally you must communicate your choice in order for them to properly free the API (windows for instance can allocate from several different places).
The second approach has some advantages like
It lets callers manage the lifetime of memory allocations
It lets callers to reuse allocated memory for different calls that follow that same pattern
It lets callers to decide which
buffer to provide e.g. stack or heap.

Resources