【问题标题】:Using throw keyword in a function produces a warning with gcc在函数中使用 throw 关键字会产生带有 gcc 的警告
【发布时间】:2015-12-03 12:44:15
【问题描述】:

我需要找到一种方法(请使用 C++03,不能使用 C++11)来消除 gcc 在以下(伪)代码上产生的警告:

#include <stdexcept>

void throw_invalid()
{
  throw std::invalid_argument( "invalid" );
}

int foo(const char * str)
{
  if( str ) return 42;
  throw_invalid();
  // insert portable -fake- code that will get optimized away
}

我的代码至少需要在 gcc 5.x (-Wall) 和 Visual Studio 上无警告。我的throw_invalid 函数用于避免样板代码,并将异常集中在与无效参数相关的单个函数中。

目前的警告是:

$ g++ -Wall -c foo.cxx 
b.cxx: In function ‘int foo(const char*)’:
b.cxx:13:1: warning: control reaches end of non-void function [-Wreturn-type]
 }
 ^

我想避免添加虚假的return -1(从未达到),因为它会使代码更难阅读。

【问题讨论】:

    标签: c++ gcc portability throw


    【解决方案1】:

    在 c++11 中,您可以使用 attribute specifier [[noreturn]]

    像这样:

    [[noreturn]] void throw_invalid()
    {
         throw std::invalid_argument( "invalid" );
    }
    
    int foo(const char * str)
    {
        if( str ) return 42;
        throw_invalid();
        // insert portable -fake- code that will get optimized away
    }
    

    更新

    就像 Walter 在他的评论中提到的那样,即使函数 foo 是非 void 函数并且是触发错误的函数,但需要该属性的是函数 throw_invalid。将throw_invalid 设置为noreturn 将告诉编译器foo 也不会在使用带有函数throw_invalid 的代码路径时返回。

    【讨论】:

    • @Default 非空函数为foo(),编译器会发出警告,因为它没有返回值。但是,永远无法到达此函数的末尾,因为throw_invalid() 永远不会返回。这个答案中提供的解决方案告诉编译器这个事实,这样它就可以避免虚假警告。
    【解决方案2】:

    据我了解,在进行任何计算之前,您首先需要确保您的参数有效。话虽如此,我相信你可以通过相应地重写你的代码来克服这个问题

    在您的示例中,类似这样的内容:

    int foo(const char * str)
    {
       // Make sure that str is valid
       if( str == NULL ) throw_invalid();
    
       return 42;
    }
    

    【讨论】:

    • 这仅适用于简单的示例,但在某些情况下,您无法以这种方式重新排序代码(不会降低效率或以其他方式改变它)。
    【解决方案3】:

    对于 GCC,您可以将 noreturn 属性添加到方法中:

    void throw_invalid()
    #ifdef __GNUC__
        __attribute__ ((noreturn))
    #else
        // something here for Visual Studio
    #endif
    {
      throw std::invalid_argument( "invalid" );
    }
    

    手册说:

    noreturn 关键字告诉编译器假设“致命” 无法返回。然后它可以优化而不考虑什么 如果函数确实返回,就会发生。这使得代码稍微好一点。 更重要的是,它有助于避免未初始化的虚假警告 变量。

    noreturn 关键字不影响异常路径时 这适用:noreturn 标记的函数可能仍会返回到 调用者通过抛出异常或调用longjmp

    我对你的其他编译器没有经验,所以无法填补那里的空白;对不起。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-03-27
      • 1970-01-01
      • 2021-09-08
      • 1970-01-01
      • 2014-10-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多