Any way to know how much memory has been allocated on the stack?

Let’s say I’m using some recursive algorithm which risks a stack overflow, if I can detect that and deal with it somehow then I’d prefer that over a crash. Is it possible?

This isn’t Odin-specific, but it’s my understanding that you can always convert an algorithm with recursive procedure calls into a single procedure call that uses an explicit stack (think Depth First Search implementations that use The Stack vs. an explicit stack). That would give you visibility into what you allocate and you can bail when you see that you exceed the bounds of the stack.

It would be super cool if there was a context.stack_allocator that you could override with your own tracking stack allocator and existing stack allocations just worked… although I’m not sure if that’s even possible to implement.

I have a solution that kinda works but it’s also kind of hacky. It probably won’t work on all platforms.

package recurse_test

import "core:fmt"

stack_ptr_begin: rawptr

get_used_stack_mem :: #force_no_inline proc "c" () -> int {
	current: int
	// stack may grow downwards or upwards, and downwards is more common so abs in needed
	return abs(int(uintptr(&current) - uintptr(stack_ptr_begin)))
}

main :: proc() {
	start: int
	stack_ptr_begin = &start
	func()
}

ptr: rawptr

func :: proc() {
	@(static) i: int
	i += 1

	a, b: [64]uint
	c := a + b

	// to avoid optimizing out c
	ptr = &c

	used := get_used_stack_mem()
	fmt.println(used)

	if used < (1 << 19) {
		func()
	} else {
		fmt.println("out of memory at iteration", i)
	}
}
2 Likes

Why not just use tail call optimization to reuse the same stack frame?

That was just an example use case. There are other use cases for knowing the used memory on a stack. Like allocating space for fibers, although I’m not yet sure if it’s possible to implement in Odin.