__attribute __((格式(printf,1,2)))对于MSVC?

nos*_*nos 23 c c++ visual-c++

使用GCC,我可以指定__attribute__((format(printf, 1, 2))),告诉编译器该函数采用printf格式说明符的vararg参数.

这在我包装例如vsprintf函数系列的情况下非常有用.我可以有 extern void log_error(const char *format, ...) __attribute__((format(printf, 1, 2)));

每当我调用这个函数时,gcc将检查参数的类型和数量是否与printf一样符合给定的格式说明符,如果没有则发出警告.

Microsoft C/C++编译器是否有类似的东西?

use*_*116 16

使用SAL注释可以使用_Printf_format_string_(从VS2k8或VS2k10开始)或__format_string(对于VS2k5):

#undef FORMAT_STRING
#if _MSC_VER >= 1400
# include <sal.h>
# if _MSC_VER > 1400
#  define FORMAT_STRING(p) _Printf_format_string_ p
# else
#  define FORMAT_STRING(p) __format_string p
# endif /* FORMAT_STRING */
#else
# define FORMAT_STRING(p) p
#endif /* _MSC_VER */

/* use /analyze or _USE_ATTRIBUTES_FOR_SAL for checking */
extern void log_error(FORMAT_STRING(const char* format), ...);
Run Code Online (Sandbox Code Playgroud)

  • 在指定了/ analyze选项的"Enterprise"版本之外忽略. (3认同)
  • 真?为什么?即使是免费的Express Edition也是一个功能齐全的C/C++编译器,它带有一流的调试器,但可能需要"Enterprise"(大多数企业),但"Enterprise"带来的是核心编译器和调试器. (3认同)
  • `/ analyze`选项现在包含在VS社区版中.但不知何故,即使没有该选项,VS也会检测到`printf`参数的问题,但*任何自定义使用*的SAL仅在启用/ analyze时生效.如果没有/ analyze,也会忽略`#define _PREFAST_`.**[实施例](http://rextester.com/TODFQL37231)** (3认同)

doy*_*nax 6

如之前提到的@RustyX printf格式的检查现在默认支持为VC2015的。这是没有一个/analyze静态的分析过程。遗憾的是,还没有一种用于标记用户定义的包装器功能的机制。

这建议了调用printf的明显解决方法。那就是定义一个宏,该宏既调用用户定义的函数,又调用其printf自身。后者在一条死路上需要优化。

这具有实现到其他编译器某种程度的可移植性的额外好处。

int printf_wrapper_(const char *format, ...);

#define printf_wrapper(...) \
(printf || printf(__VA_ARGS__), printf_wrapper_(__VA_ARGS__))
Run Code Online (Sandbox Code Playgroud)

缺点是VC2015在进行格式检查之前会执行一些基本的死代码消除操作,仅测试剩余的活动代码。

因此sizeof,常量条件表达式将失败。根据经验,如果调试版本发出运行时代码,则您会收到警告,尽管发行版本中的后续传递仍可能会终止调用。

las,这使其成为可能在将来的编译器版本中更改的移动目标。尽管是相对良性的。


Cli*_*ord 5

虽然在启用-Wformat时GCC会检查格式说明符,但VC ++没有进行这种检查,即使对于标准函数也是如此,因此没有等效检查,__attribute__因为没有等效于-Wformat的检查。

我认为Microsoft对C ++的重视(通过保持对C ++的ISO兼容性而仅支持C89来证明)可能部分是VC ++没有格式说明符检查的原因。在C ++ <iostream>中,不需要使用格式说明符。