In other words, use heap space and not stack space. This is pretty elementary in C programming.
Sure, but 128 kB is really small even if you do that properly. Seems like it would be more sensible if the stack space could just grow when required. Surely not that difficult?
Understanding thread stack sizes and how Alpine is different
11–20 of 81 posts
Re: Understanding thread stack sizes and how Alpine is different
#12In other words, use heap space and not stack space. This is pretty elementary in C programming.
Sure, but 128 kB is really small even if you do that properly. Seems like it would be more sensible if the stack space could just grow when required. Surely not that difficult?
For the main thread, a system can also try to keep other allocations far from the stack without committing to any particular size (heap grows upwards from the bottom of the address space, stack downwards from the top). But this doesn't scale to multiple threads and leads to an unpredictable maximum stack size, so I prefer the fixed reserved space approach.
Re: Understanding thread stack sizes and how Alpine is different
#13How can you write a program that runs without at least some guaranteed stack size? Are you at fault if you program doesn't run in a 1kb stack? And how do you work out what stack size your program takes from looking at the source code? I guess make sure your required stack size is not a function of input, and test against a minimum stack size.
Unless you do alloca() or dynamically sized local arrays, you can measure your stack usage in the deepest call stack. Add some space in each frame for potential instrumentation and you have your minimum. Keep in mind that this is just for thread stacks - you can set the size for them yourself, so ideally you'd always do it. Then a guaranteed minimum size becomes irrelevant.
How does a normal working programmer calculate the size of each of their stack frames? I'm a compiler researcher and I'd struggle to do that. How are application developers going to do it?
And how do you design a program to have a deterministic maximum call stack depth?
I don't think these things are as easy as you're making out.
Re: Understanding thread stack sizes and how Alpine is different
#14That seems pretty strange to modern ears, but maybe the underlying point was that it isn't possible to statically know how much stack size would be required.
I suppose it wouldn't have been obvious then that if you fudge the issue for the first thirty years or so, everyone will just accept that this is the way the world is.
Still, it's a bit of a shame that there are still widely-used systems where if you exceed the available stack space you're likely to face a "weird crash" rather than a clean error message at runtime.
Re: Understanding thread stack sizes and how Alpine is different
#15Earlier quoted context omitted.
Unless you do alloca() or dynamically sized local arrays, you can measure your stack usage in the deepest call stack. Add some space in each frame for potential instrumentation and you have your minimum. Keep in mind that this is just for thread stacks - you can set the size for them yourself, so ideally you'd always do it. Then a guaranteed minimum size becomes irrelevant.
> Unless you do alloca() or dynamically sized local arrays, you can measure your stack usage in the deepest call stack. How does a normal working programmer calculate the size of each of their stack frames? I'm a compiler researcher and I'd struggle to do that. How are application developers going to do it? And how do you design a program to have a deterministic maximum call stack depth? I don't think these things ar…
I know that in the small-embedded world, people do work on such things.
Re: Understanding thread stack sizes and how Alpine is different
#16Earlier quoted context omitted.
Unless you do alloca() or dynamically sized local arrays, you can measure your stack usage in the deepest call stack. Add some space in each frame for potential instrumentation and you have your minimum. Keep in mind that this is just for thread stacks - you can set the size for them yourself, so ideally you'd always do it. Then a guaranteed minimum size becomes irrelevant.
> Unless you do alloca() or dynamically sized local arrays, you can measure your stack usage in the deepest call stack. How does a normal working programmer calculate the size of each of their stack frames? I'm a compiler researcher and I'd struggle to do that. How are application developers going to do it? And how do you design a program to have a deterministic maximum call stack depth? I don't think these things ar…
In those leaf functions you can check &local_var and compare it to pthread_attr_getstack(pthread_getattr_np()). (Of course that's not precise for many reasons.)
> And how do you design a program to have a deterministic maximum call stack depth?
If you're running only your code - don't use recursion, or alloca. If you use external libraries, you have to research what they do and add some extra in case of updates.
Bounded stack size is also a common issue if you're targeting small microprocessors.
For non-critical apps it should be pretty easy to figure out the needed stack size. For cases when you want to guarantee it... that gets more tricky.
Edit: just learned that clang has the option -fstack-usage which should help a lot.
Re: Understanding thread stack sizes and how Alpine is different
#17As far as I can tell this is something they think in principle should be changed.
Re: Understanding thread stack sizes and how Alpine is different
#18How can you write a program that runs without at least some guaranteed stack size? Are you at fault if you program doesn't run in a 1kb stack? And how do you work out what stack size your program takes from looking at the source code? I guess make sure your required stack size is not a function of input, and test against a minimum stack size.
But in my experience you don't really compute a "guaranteed" stack size, you use your experience and knowledge of the program to make an educated guess, and then you apply a reasonable multiplier to give you some security margin.
If you don't use (or severely limit) recursive calls you can usually just check that your deepest call stack fits within the bounds. Although finding the deepest call stack in the first place can be tricky given that compilers can aggressively inline function calls.
Re: Understanding thread stack sizes and how Alpine is different
#19How can you write a program that runs without at least some guaranteed stack size? Are you at fault if you program doesn't run in a 1kb stack? And how do you work out what stack size your program takes from looking at the source code? I guess make sure your required stack size is not a function of input, and test against a minimum stack size.
Re: Understanding thread stack sizes and how Alpine is different
#20How can you write a program that runs without at least some guaranteed stack size? Are you at fault if you program doesn't run in a 1kb stack? And how do you work out what stack size your program takes from looking at the source code? I guess make sure your required stack size is not a function of input, and test against a minimum stack size.