void *get_sp(void) {
volatile char c;
return (void *)&c;
}
Or, in GCC and Clang: void *get_sp(void) {
return __builtin_frame_address(0);
}
Which gets you close enough.Does such thing even exist? And non-64 bit platforms the address space is small enough that with several threads of execution you may just be unable to grow your stack even up to $system_stack_size because it'd bump into something else.
AFAIK no. There are default stack sizes, but they're just that, defaults, and they can vary on the same system: main thread stacks are generally 8MiB (except for Windows where it's just 1) but the size of ancillary stacks is much smaller everywhere but on linux using glibc.
It should be possible to get the stack root and size using `pthread_getattr_np`, but I don't know if there's anyone bothering with that, and it's a glibc extension.
[1]: https://learn.microsoft.com/en-us/dotnet/api/system.runtime....
[2]: https://github.com/dotnet/runtime/blob/b6a3e784f0bb418fd2fa7...
Stack memory is weird in general. It's usually a fixed amount determined when the thread starts, with the size typically determined by vibes or "seems to work OK." Most programmers don't have much of a notion of how much stack space their code needs, or how much their program needs overall. We know that unbounded non-tail recursion can overflow the stack, but how about bounded-but-large? At what point do you need to start considering such things? A hundred recursive calls? A thousand? A million?
It's all kind of sketchy, but it works well enough in practice, I suppose.
1. I know that the function will never be called recursively and
2. the total amount of stack allocation is limited to a few kilobytes at most.
alloca() is more problematic on embedded platforms because default stack sizes tend to be tiny. Either document your stack usage requirements or provide an option to disable all calls to alloca(). For example, Opus has the OPUS_NONTHREADSAFE_PSEUDOSTACK option.