__attribute__((format(printf, 1, 2))) for MSVC?

后端 未结 4 1658
半阙折子戏
半阙折子戏 2020-12-03 17:01

With GCC, I can specify __attribute__((format(printf, 1, 2))) , telling the compiler that this function takes vararg parameters that are printf format specifie

相关标签:
4条回答
  • 2020-12-03 17:44

    There is an interesting article on the subject on Code Project: "Using C++ Templates for Startup Validation" by Alexander Gorobets http://www.codeproject.com/KB/cpp/ValidateprintfFunction.aspx

    I've modified it so that I have a macro PRINTF_VALIDATE(format, ...) that logs all format errors at program statup (there's no need to actually execute the code). It produces something like this:

    test.cpp(147) : error : 'printf' format character 'f' at position 1 does not match parameter type INT
    test.cpp(147) : error : 'printf' too many arguments (3 instead of 2)
    

    One can use it for example like this:

    #define LOG(fmt, ...) do { PRINTF_VALIDATE(fmt, __VA_ARGS__); WriteLog(fmt, __VA_ARGS__); } while(0)
    

    This is not as useful as compiler support, but it works on Visual Studio 2005...

    0 讨论(0)
  • 2020-12-03 17:46

    As previously mentioned by @RustyX printf format checking is now supported by default as of VC2015. That is without a /analyze static analysis pass. Regrettably there is not yet a mechanism for marking user-defined wrapper functions.

    This suggest the obvious workaround of calling printf. That is defining a macro which invokes both the user-defined function as well as the printf itself. The latter on a dead path to be optimized out.

    This has the added benefit of achieving some level of portability to other compilers.

    int printf_wrapper_(const char *format, ...);
    
    #define printf_wrapper(...) \
    (printf || printf(__VA_ARGS__), printf_wrapper_(__VA_ARGS__))
    

    The drawback is that VC2015 performs some rudimentary dead-code elimination prior to the format check, testing only the remaining live code.

    Thus sizeof or constant conditional expressions will fail. As a rule of thumb if a debug build emits run-time code then you will get the warning, though later passes in release builds may still kill the call.

    Alas this makes it something of a moving target liable to change in future compiler versions. Albeit a relatively benign one.

    0 讨论(0)
  • 2020-12-03 17:48

    Using SAL Annotations you can use _Printf_format_string_ (as of VS2k8 or VS2k10) or __format_string (for 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), ...);
    
    0 讨论(0)
  • 2020-12-03 17:50

    While GCC checks format specifiers when -Wformat is enabled, VC++ has no such checking, even for standard functions so there is no equivalent to this __attribute__ because there is no equivalent to -Wformat.

    I think Microsoft's emphasis on C++ (evidenced by maintaining ISO compliance for C++ while only supporting C89) may be in part the reason why VC++ does not have format specifier checking; in C++ using <iostream> format specifiers are unnecessary.

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