我发现__attribute__ ((warn_unused_result))作为鼓励开发人员不要忽略函数返回的错误代码的一种非常有用的方法,但是我需要将它与MSVC以及gcc和gcc兼容的编译器(例如ICC)一起使用。 Microsoft Visual Studio C / C ++编译器是否具有等效的机制? (到目前为止,我已经尝试通过MSDN进行尝试,但是没有任何运气。)
当然,这叫做例外。
@DeadMG:是的,不幸的是那还不如编译器警告那么直接,通常其他人必须解决该问题。
_Check_return_。有关类似注释的示例,请参见此处;有关功能行为,请参见此处。自MSVC 2012开始受支持。
例:
_Check_return_
int my_return_must_be_checked() {
return 42;
}
非常感谢-最初的问题是在2010年提出的,当时显然在MSVC中不存在此问题,但是很高兴知道现在已添加了它。我猜一个人可以实现一个宏,该宏先检查_MSCVER,然后使用_Check_return_(如果受支持)。
Ive现在将此答案作为可接受的答案,因为它比以前的答案更新了。香港专业教育学院还添加了我自己的答案,其中包括一个跨平台的宏,用于检查MSVC版本等。再次感谢!
还有_Must_inspect_result_
MSVC 2012及更高版本的更新
非常感谢@Albert指出,在使用SAL静态代码分析时,MSVC现在从Visual Studio 2012开始支持注释_Check_return_。我添加此答案,以便可以包含一个跨平台宏,该宏可能对其他人有用:
#if defined(__GNUC__) && (__GNUC__ >= 4)
#define CHECK_RESULT __attribute__ ((warn_unused_result))
#elif defined(_MSC_VER) && (_MSC_VER >= 1700)
#define CHECK_RESULT _Check_return_
#else
#define CHECK_RESULT
#endif
请注意,与gcc等人不同,(a)MSVC在函数的声明和定义上都需要注释,并且(b)注释需要在声明/定义的开始(gcc允许其中之一)。因此,用法通常需要为:
// foo.h
CHECK_RETURN int my_function(void); // declaration
// foo.c
CHECK_RETURN int my_function(void) // definition
{
return 42;
}
还请注意,如果从命令行进行编译,则需要/analyze(或-analyze)开关,如果使用Visual Studio IDE,则需要进行等效操作。这也会使构建速度变慢。
某些版本的VisualStudio附带了一个静态分析工具,该工具以前称为PREFast(现在简称为" C / C ++代码分析")。 PREFast使用注释来标记代码。其中之一便是MustCheck,它可以满足您的需求。
看起来很有趣-您可以修复MustCheck的链接吗?
@John + @Paul:microsoft.com/whdc/devtools/tools/annotations.mspx __checkReturn批注;)
现在,Prefast称为C / C ++代码分析-msdn.microsoft.com/en-us/library/d3bbz7tz.aspx
@Paul:固定。抱歉。 @ Billy,@ Steve:谢谢,编辑
谢谢-这似乎可以解决问题-我们使用cl和makefile构建,因此在构建时添加prefast选项应该足够容易。
@Paul R-请注意,这将大大减慢您的构建速度,并生成许多您可能不关心的警告。我会定期执行此操作,而不是在每次构建时都执行此操作,以避免对有价值的工具产生负面反馈。
@Steve:谢谢-注意-我不确定我是否能够说服所有人安装此东西,但可能会使其成为选择安装的可选步骤。
现在在当前的代码分析实现中将其称为Check_return。
@bfulgham:感谢您提供信息。我最近主要是离开VS堆栈。您能用任何可以提供的新信息来编辑我的答案吗?甚至提供您自己的答案。
据我所知,MS编译器没有等效的编译指示或属性-当您以适当的警告级别打开优化器时,可以获得的唯一"未使用"类型警告是变量。
谢谢-有点讽刺的是,最需要此平台的平台是其编译器不支持该平台的平台。
我认为其他人提到的SAL注释是正确的
MSVC的答案,但我想有些人会对
不仅具有MSVC,GCC和与GCC兼容的编译器,还具有更多的可移植性,
所以…
首先,GCC从3.4开始仅支持warn_unused_result。你可以
想要检查__GNUC__ / __GNUC_MINOR__的值,而不是
只是检查是否定义了__GNUC__,尽管在??这一点上我已经
想像不到任何人使用的GCC版本早于3.4。
一些编译器支持GCC样式的函数属性,并且可能或
可能未定义__GNUC__和朋友:
叮当声(用__has_attribute(warn_unused_result)检查),和
不过,基于它的编译器(emscripten,xlc 13 +,armclang等)
AFAIK至少会伪装成GCC 4.2,所以您可能
不需要显式检查。
英特尔并不总是定义__GNUC__(请参阅-no-gcc标志)。一世
不知道他们何时开始支持它(他们的文档是
严重缺乏),但我知道16.0+是安全的。
TI 8.0+支持它
传递--gcc时,TI 7.3+支持它。
__TI_GNU_ATTRIBUTE_SUPPORT__将在定义时定义。
Oracle Developer Studio 12.6+支持C ++模式,但不支持
C。
PGI在C ++模式下支持它。 AFAICT没有证件,所以我没有
确定何时添加(它是#1650-D),但肯定存在
在17.10以上。在C模式下它被默默忽略,希望他们会
有一天实施。
此外,C ++ 17添加了[[nodiscard]]属性。对于版本
GCC / clang在C ++ 17模式下支持[[nodiscard]],您也可以使用
在C ++ 11和更高版本模式下为[[gnu::nodiscard]],但如果您隐藏
无论如何,它都在宏后面,我看不出这样做的理由,而不是
仅使用__attribute__((__warn_unused_result__))。
放在一起,Hedley中有一个HEDLEY_WARN_UNUSED_RESULT宏,如下所示:
#if defined(__cplusplus) && (__cplusplus >= 201703L)
# define HEDLEY_WARN_UNUSED_RESULT [[nodiscard]]
#elif \
HEDLEY_GNUC_HAS_ATTRIBUTE(warn_unused_result,3,4,0) || \
HEDLEY_INTEL_VERSION_CHECK(16,0,0) || \
HEDLEY_TI_VERSION_CHECK(8,0,0) || \
(HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
(HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
HEDLEY_PGI_VERSION_CHECK(17,10,0)
# define HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
#elif defined(_Check_return_) /* SAL */
# define HEDLEY_WARN_UNUSED_RESULT _Check_return_
#else
# define HEDLEY_WARN_UNUSED_RESULT
#endif
您应该能够去除内部的Hedley宏,并且
如果您不想使用,则复制逻辑不会有太多麻烦
赫德利(这是公共领域/ CC0)。如果您选择这样做,则应该
可能是因为您的端口基于仓库中的版本,而我要少得多
可能会记得使这个答案与最新的
信息。