C++ Logo


Advanced search

Re: [std-proposals] Monitor recursion by checking the frame pointer

From: Sebastian Wittmeier <wittmeier_at_[hidden]>
Date: Mon, 17 Apr 2023 14:25:43 +0200
Hi Frederick, there is no need that an architecture running C++ has a stack for storing return addresses. Also the optimizer may inline functions or optimize them out altogether. I think those ideas are too low-level and outside the scope of the standard and should be implementation or better implementation and architecture specific within each of the compilers.   You also saw yourself that you cannot detect indirect recursion in a simple way, even if no inlining happened. This approach is not really stable / reliable for detecting recursion.   Why not just use a thread-local static bool variable?   -----Ursprüngliche Nachricht----- Von:Frederick Virchanza Gotham via Std-Proposals <std-proposals_at_[hidden]> Gesendet:Mo 17.04.2023 13:09 Betreff:[std-proposals] Monitor recursion by checking the frame pointer An:std-proposals <std-proposals_at_[hidden]>; CC:Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>; Lately I've been messing around trying to write assembler thunks for invoking lambdas without the hidden 'this' paramater, and I had to consider the complications of multi-threading, and also of recursive function calls. Let me stick to single-threaded programs for now. I will use the term 'caller' to describe a recursive function which contains a lambda, so something like:    extern void SomeLibraryFunc( void(*)(void) );    void Func(int const arg)    {        if ( -1 == arg ) return;        auto mylambda = [arg](void)->void { /* do something */ };        SomeLibraryFunc( thunk(mylambda) );        Func(arg - 1);    } In order to write an efficient implementation of the thunk generator to accommodate recursive calls, I was thinking it would be cool if I could somehow get the thunk to correctly identify whether the caller has been re-entered since the thunk was generated. Then I realised that this could be ascertained from the stack pointer (i.e. the RSP register on x86_64, or the x31sp register on aarch64). As a function is executed though, it might push and pop and push and pop, and so the stack pointer would be going up and down by 8 bytes here and there, it would be fluctuating a little. But if the frame pointer is used instead (i.e. the RBP register on x86_64, or the x29FP register on aarch64), then it could be used to reliably check if re-entry has occurred. What if the Standard library were to have:    namespace std {        void *frame_pointer(void) noexcept;        void *stack_pointer(void) noexcept;    } The contents of "frame_and_stack_pointer.S" on x86_64 could be:        frame_pointer:            mov rax,rbp            ret        stack_pointer:            mov rax,rsp            add rax,8     ; disregard the return address on top of stack            ret Also maybe it would be helpful if the return address were available too, something like:    namespace std {        void (*return_address(void))(void) noexcept;    } The contents of "return_address.S" on x86_64:        return_address:            mov rax,[rsp]  ; return address is at top of stack            ret Nine times out of ten, the return address will just be the 8 bytes at the top of the stack, but it won't be if the function has supernumerary parameters or a very big return type, so the compiler would have to be a bit smarter. If the function "std::frame_pointer" is invoked inside a function that was compiled with a compiler flag to prevent the use of a frame pointer (e.g. '-fomit-frame-pointer' on the GNU g++ compiler), or if it is a very simply function that doesn't use the stack and so doesn't bother with a frame pointer, then it should return a nullptr. -- Std-Proposals mailing list Std-Proposals_at_[hidden] https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

Received on 2023-04-17 12:25:45