1
votes

The stacker crate provides a function that can optionally run a closure on a newly allocated stack.

pub fn maybe_grow<R, F: FnOnce() -> R>(
    red_zone: usize, stack_size: usize, f: F) -> R

This function will check to see if we’re within red_zone bytes of the end of the stack, and if so it will allocate a new stack of at least stack_size bytes.

The closure f is guaranteed to run on a stack with at least red_zone bytes, and it will be run on the current stack if there’s space available.

I am wondering if there is any way to get the size of the stack frame used by f so that we can guarantee for sure that the red_zone will be larger, rather than using some heuristic value for red_zone.

For example, I would like to have an implementation of stack_frame_size<F>(f: &F) -> usize such that I can perform the following.

pub fn safely_grow<R, F: FnOnce() -> R>(
    stack_size: usize, f: F) -> R {
    let sf_size = stack_frame_size(&f);

    // Always make sure that the remaining stack size
    // is greater than what we need by a margin.
    maybe_grow(sf_size + 32, stack_size, f)
}

Is this possible and how to implement it?

1
you want to calculated the stack needed ? that impossible, if it would rustc and every compiler would do it.Stargateur

1 Answers

0
votes

In the general case, this is not possible. Consider a simple FnOnce() which calls some other function MaybeRecursive(), which in turn calls itself based on some condition determined during execution. Such a FnOnce() may grow its stack frame to infinity (failing at that in practice) or it might return immediately. Determining the stack frame size would require pre-computing that FnOnce() at compile-time given the parameters at runtime, which is infeasible in practice. The halting problem lurks underneath.