Why does “noreturn” function return?

前端 未结 9 1589
执念已碎
执念已碎 2020-12-25 10:51

I read this question about noreturn attribute, which is used for functions that don\'t return to the caller.

Then I have made a program in C.

         


        
相关标签:
9条回答
  • 2020-12-25 11:02

    The noreturn attribute is a promise that you make to the compiler about your function.

    If you do return from such a function, behavior is undefined, but this doesn't mean a sane compiler will allow you to mess the state of the application completely by removing the ret statement, especially since the compiler will often even be able to deduce that a return is indeed possible.

    However, if you write this:

    noreturn void func(void)
    {
        printf("func\n");
    }
    
    int main(void)
    {
        func();
        some_other_func();
    }
    

    then it's perfectly reasonable for the compiler to remove the some_other_func completely, it if feels like it.

    0 讨论(0)
  • 2020-12-25 11:04

    no return function does not save the registers on the entry as it is not necessary. It makes the optimisations easier. Great for the scheduler routine for example.

    See the example here: https://godbolt.org/g/2N3THC and spot the difference

    0 讨论(0)
  • 2020-12-25 11:05

    According to this

    If the function declared _Noreturn returns, the behavior is undefined. A compiler diagnostic is recommended if this can be detected.

    It is the programmer's responsibility to make sure that this function never returns, e.g. exit(1) at the end of the function.

    0 讨论(0)
  • 2020-12-25 11:05

    ret simply means that the function returns control back to the caller. So, main does call func, the CPU executes the function, and then, with ret, the CPU continues execution of main.

    Edit

    So, it turns out, noreturn does not make the function not return at all, it's just a specifier that tells the compiler that the code of this function is written in such a way that the function won't return. So, what you should do here is to make sure that this function actually doesn't return control back to the callee. For example, you could call exit inside it.

    Also, given what I've read about this specifier it seems that in order to make sure the function won't return to its point of invocation, one should call another noreturn function inside it and make sure that the latter is always run (in order to avoid undefined behavior) and doesn't cause UB itself.

    0 讨论(0)
  • 2020-12-25 11:05

    The function specifiers in C are a hint to the compiler, the degree of acceptance is implementation defined.

    First of all, _Noreturn function specifier (or, noreturn, using <stdnoreturn.h>) is a hint to the compiler about a theoretical promise made by the programmer that this function will never return. Based on this promise, compiler can make certain decisions, perform some optimizations for the code generation.

    IIRC, if a function specified with noreturn function specifier eventually returns to its caller, either

    • by using and explicit return statement
    • by reaching end of function body

    the behaviour is undefined. You MUST NOT return from the function.

    To make it clear, using noreturn function specifier does not stop a function form returning to its caller. It is a promise made by the programmer to the compiler to allow it some more degree of freedom to generate optimized code.

    Now, in case, you made a promise earlier and later, choose to violate this, the result is UB. Compilers are encouraged, but not required, to produce warnings when a _Noreturn function appears to be capable of returning to its caller.

    According to chapter §6.7.4, C11, Paragraph 8

    A function declared with a _Noreturn function specifier shall not return to its caller.

    and, the paragraph 12, (Note the comments!!)

    EXAMPLE 2
    _Noreturn void f () {
    abort(); // ok
    }
    _Noreturn void g (int i) { // causes undefined behavior if i <= 0
    if (i > 0) abort();
    }
    

    For C++, the behaviour is quite similar. Quoting from chapter §7.6.4, C++14, paragraph 2 (emphasis mine)

    If a function f is called where f was previously declared with the noreturn attribute and f eventually returns, the behavior is undefined. [ Note: The function may terminate by throwing an exception. —end note ]

    [ Note: Implementations are encouraged to issue a warning if a function marked [[noreturn]] might return. —end note ]

    3 [ Example:

    [[ noreturn ]] void f() {
    throw "error"; // OK
    }
    [[ noreturn ]] void q(int i) { // behavior is undefined if called with an argument <= 0
    if (i > 0)
    throw "positive";
    }
    

    —end example ]

    0 讨论(0)
  • 2020-12-25 11:10

    Why function func() return after providing noreturn attribute?

    Because you wrote code that told it to.

    If you don't want your function to return, call exit() or abort() or similar so it doesn't return.

    What else would your function do other than return after it had called printf()?

    The C Standard in 6.7.4 Function specifiers, paragraph 12 specifically includes an example of a noreturn function that can actually return - and labels the behavior as undefined:

    EXAMPLE 2

    _Noreturn void f () {
        abort(); // ok
    }
    _Noreturn void g (int i) {  // causes undefined behavior if i<=0
        if (i > 0) abort();
    }
    

    In short, noreturn is a restriction that you place on your code - it tells the compiler "MY code won't ever return". If you violate that restriction, that's all on you.

    0 讨论(0)
提交回复
热议问题