to answer comments ...
huh, that was the first blog of mine attracting comments actually ... so I'll try to answer them as well as I may.
- How about stack growth direction ?
Well, for one thing, the method I presented isn't portable because stack_inbounds() is a Solaris-specific interface. So if you'd like to use that, you can reasonably assume that the stack grows downward, as the program used for illustration did.
Second, even assuming that either stack_inbounds() and friends ever get ported to operating environments other than Solaris, or else that Solaris ever gets ported to hardware platforms / ABIs whose stacks grow upwards, and a truly portable approach is needed, then the following strategy can be used. The approach is outlined e.g. in the 'USAGE' section of sigstack(3C). One can test for stack growth direction e.g. by passing the address of a local variable as a parameter to a function, who compares it with the address of a local variable of its own and returns true/false depending on whether the latter is larger/smaller than the former.
Or, for a more portable approach that would not require knowledge of addresses of local variables (a notoriously difficult thing given that optimizing compilers can have very interesting strategies for dealing with seemingly 'unneeded' local variables), one could use something like:#include <ucontext.h> #include <sys/types.h> int can_alloca(size_t sz) { char *buf = alloca(sz); return (stack_inbounds(buf) && stack_inbounds(&buf[sz - 1])); } void myfunc_that_does_alloca(...) { int use_alloca = can_alloca(sz); if (use_alloca) buf = alloca(sz); else buf = malloc(sz); [ ... ] if (!use_alloca) free (buf); }which is slightly more expensive than the first example shown, but might still be more lightweight than using malloc() since definitely no syscalls are involved and no "malloc bookkeeping" is needed.
But then, I didn't claim the approach is for everyone, and neither did I suggest to prefer alloca() over malloc(). There are some pretty good malloc implementations out there - even in Solaris, you have the choice of several, and benchmarks often select a specific in order to achieve best results.
But I'm disgressing now - differences between the various malloc libraries should better be covered in another blog entry ... one day ...
Finally - before I forget, try "I'm feeling lucky" on a Google search for "stack growth direction". - What's the advantage to C99 vararrays ?
C99 VLAs and alloca() are pretty much equivalent, and that goes both for advantages and disadvantages. There is nothing in the C99 standard that guarantees you success on declaring a VLA, or respectively, for all I know, it's not defined what happens if the stack cannot be extended to accommodate the requested VLA size. Which is exactly the behaviour of alloca() as well. Hence, if it's important / critical to know that the C99 function using variable-length arrays will never crash (due to attempting to use a too-large VLA), the same approach, testing whether the addresses of all elements of the VLA are within the stack boundaries, would suffice.
Regarding variable length arrays and C/C++ programming, this paper by Dennis Ritchie and this discussion on CodeGurus also make interesting reads. Some things are just notoriously hard ...
To put it short: C99 VLAs and alloca() are, in my opinion, very close cousins and share common (dis)advantages. That includes the inability to check for 'success' in simple ways, and the applicability of the shown strategy to achieveit nonetheless.
And now - I need to find out how to actually post replies to comments without needing to write another blog article. You, the readers, might eventually turn this "blogophobe me" into a real blogger - who'd have thought that ...
