mulle-alloca for safe stack allocations
Use mulle_alloca_do
like a better alloca
mulle-allocator provides the mulle_alloca_do
macro for stack based
storage, that gets swapped to heap based when the size exceeds a certain
compile time size.
What is
alloca
? Excerpts fromman alloca
The alloca() function allocates size bytes of space in the stack frame of the caller. This temporary space is automatically freed the function that called alloca() returns to its caller… There is no error indication, if the stack frame cannot be extended… For certain applications, its use can improve efficiency compared to the use of malloc plus free… Otherwise, its use is discouraged…
Here is an example function, where the use of alloca
avoids a malloc
and free
call. Getting stack space is super cheap and the
automatic reclamation makes the code easier to write:
void print_uppercase( char *s)
{
char *copy;
size_t i;
size_t len;
len = strlen( s) + 1;
copy = alloca( len);
for( i = 0; i < len; i++)
copy[ i] = toupper( s[ i]);
printf( "%s\n", copy);
}
The problems are two-fold: alloca
may not be available (or is
“hidden” in a non standard header, which decreases portability). The length
of s
is unknown and the available stack size is also unknown. So this code
is likely to crash for large strings. How large ? Hard to say…
mulle_alloca_do
uses a certain safe amount (the default is 128 bytes) of
stack space for a temporary allocation.
Note
What is a safe amount ? The author thinks
double[8]
should be fine. If your system is very tiny or very large, you can set MULLE_ALLOCA_STACKSIZE to a size of your liking. Remember though, that if you call other functions that also usemulle_alloca_do
the reasonable stack size is halved (and so on). Usemulle_alloca_do_flexible
if you want to set the stack size per macro invocation.
But if the requests exceed this amount mulle_alloca_do
will fallback to
malloc/free. See above code transformed to mulle_alloca_do
:
void print_uppercase( char *s)
{
// char *copy; // no longer needed, will be declared in mulle_alloca_do
size_t i;
size_t len;
len = strlen( s) + 1;
mulle_alloca_do( copy, char, len) // need type to alloca for alignment
{
for( i = 0; i < len; i++)
copy[ i] = toupper( s[ i]);
printf( "%s\n", copy);
}
}
The scope of copy
is now tied to mulle_alloca_do
and not the function!
/* copy not yet in scope */
mulle_alloca_do( copy, char, size)
{
/* code block, where copy is valid */
}
/* copy no longer in scope (and freed) */
Post a comment
All comments are held for moderation; basic HTML formatting accepted.