Why “not all control paths return a value” is warning and not an error?

后端 未结 7 1782
花落未央
花落未央 2020-12-02 01:48

I was trying to answer this question. As suggested by the accepted answer, the problem with that code is that not all control paths are returning a value. I tried this code

相关标签:
7条回答
  • 2020-12-02 02:03

    Another example where it may be okay for some control paths to not return a value:

    enum E : int {A, B};
    
    int foo(E e) {
      switch (e) {
        case A: return 30;
        case B: return 50;
      }
    }
    

    It's possible that e won't be A or B, but the implication is that it always will be one of those values. If that's the case then the code is fine and there's no problem. Making this warning into a mandatory error would require unnecessary, 'unreachable' clutter.

    If you want the warning to be an error anyway, you can configure your compiler to do that with a flag like /WX or -Werror. Though of course you should note that different compilers may make different determinations as to what's unreachable so you may be fixing different things for different compilers.

    0 讨论(0)
  • 2020-12-02 02:05

    here is another reason it isn't an error

    the following will give you the same warning since the compiler expects you to return something from the catch block even though you're throwing there

    int foo(){
       try{
          return bar(0);
       } catch(std::exception& ex){
          //do cleanup
          throw ex;
       }
    }
    
    int bar(unsigned int i){
       if(i == 0){
          throw std::string("Value must be greater than 0");
       } else{
          return 0;
       }
    }
    
    0 讨论(0)
  • 2020-12-02 02:06

    It is not an error because it may be the intended behaviour. For example, some encryption libraries use uninitialized local data as a step for seeding. As return values are kept in calling-convention and platform specific locations, this may help in some unusual (like the above) situations. In this case, the function returns whatever is left on the register used to return the return value.

    0 讨论(0)
  • 2020-12-02 02:13

    Failing to return a value from a function that has a non-void return type results in undefined behaviour, but is not a semantic error.

    The reason for this, as far as I can determine, is largely historical.

    C originally didn't have void and implicit int meant that most functions returned an int unless explicitly declared to return something else even if there was no intention to use the return value.

    This means that a lot of functions returned an int but without explicitly setting a return value, but that was OK becase the callers would never use the return value for these functions.

    Some functions did return a value, but used the implicit int because int was a suitable return type.

    This means that pre-void code had lots of functions which nominally returned int but which could be declared to return void and lots of other functions that should return an int with no clear way to tell the difference. Enforcing return on all code paths of all non-void functions at any stage would break legacy code.

    There is also the argument that some code paths in a function may be unreachable but this may not be easy to determine from a simple static analysis so why enforce an unnecessary return?

    0 讨论(0)
  • 2020-12-02 02:20

    I would guess it is only a warning because the compiler cannot always be 100% sure it is possible to not hit a return.

    i.e. if you had:

    
    -= source1.c =-
    int func()
    {
        if(doSomething())
        {
           return 0;
        }
    }
    
    -= source2.c =-
    int doSomething()
    {
        return 1;
    }
    

    The compiler in this case might not be able to know it will always hit the return, but you do. Of course this is terrible programming practice to rely on knowing how external code works.

    As for what will actually be returned it depends on the platform. On x86 ABIs EAX is used for the return value (up to 32bits) so it will return what ever was placed in that register (which could be a return from something else, a temporary value or total garbage).

    0 讨论(0)
  • 2020-12-02 02:20

    Consider the following scenario:

    UINT GenderID(GENDER gender)
    {
        switch(gender)
        {
        case MALE:
            return MALE_ID;
        case FEMALE:
            return FEMALE_ID;
        }
    // default not required because [GENDER] in our 'Matrix' CAN be either M or F
    }
    

    a C++ complier should let you have your 'Matrix' your way; Thus its not an Error.

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