top | item 47183893

(no title)

spacechild1 | 4 days ago

alloca() is super useful, but it's also quite dangerous because you can easily overflow the stack.

The obvious issue is that you can't know how much space is left on the stack, so you basically have to guess and pick an arbitrary "safe" size limit. This gets even more tricky when functions may be called recursively.

The more subtle issue is that the stack memory returned by alloca() has function scope and therefore you must never call it directly in a loop.

I use alloca() on a regular basis, but I have to say there are safer and better alternatives, depending on the particular use case: arena/frame allocators, threadlocal pseudo-stacks, static vectors, small vector optimizations, etc.

discuss

order

12_throw_away|4 days ago

> The obvious issue is that you can't know how much space is left on the stack [...]

Oh, huh. I've never actually tried it, but I always assumed it would be possible to calculate this, at least for a given OS / arch. You just need 3 quantities, right? `remaining_stack_space = $stack_address - $rsp - $system_stack_size`.

But I guess there's no API for a program to get its own stack address unless it has access to `/proc/$pid/maps` or similar?

fluntcaps|4 days ago

You can do something like:

    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.

wat10000|3 days ago

It's certainly possible on some systems. Even then, you have to fudge, as you don't know exactly how much stack space you need to save for other things.

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.

chuckadams|4 days ago

If your API includes inline assembly, then it's trivial. Go's internals would need it to swap stacks like it does. But I doubt any of that is exposed at the language level.

Joker_vD|4 days ago

> $system_stack_size

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.

norir|4 days ago

If you have well defined boundaries, you can move the stack to an arbitrarily large chunk of memory before the recursive call and restore it to the system stack upon completion.

cyberax|3 days ago

> alloca() is super useful, but it's also quite dangerous because you can easily overflow the stack.

This is not a problem for Go, because it has resizable stacks.