2017-08-11 15 views
3

我有以下功能,我想有警告视为一个用printf当有:C++编译器添加警告,自定义打印错误使用/日志功能

void LoggingManager::log(int32_t logLevel, const char *p_str, ...) 
{ 
    va_list args; 
    va_start(args, p_str); 
    vsnprintf(s_LogginManagerBuffer, LOGGING_MANAGER_BUFFER_SIZE - 1, p_str, args); 
    va_end(args); 

    internalLog(s_LogginManagerBuffer); 
} 

我想如果我忘记在格式字符串中为其中一个标记添加参数,会出现警告。另外,有太多(或错误的参数)的警告会很棒。 由于忘记日志功能中的参数,我最近面临一些崩溃。

如果不可能这样做,我怎么能重写我的功能,有警告但功能相同?

+2

请不要用c标记,这是无效的c代码。 –

回答

4

如果您使用的GCC /克++ /铛可以使用作为this page指定的格式属性:

格式(原型,字符串索引,第一 - 校验)

format属性指定一个函数使用printf,scanf,strftime或strfmon样式参数,这些参数应该根据格式字符串进行类型检查。例如,声明:

extern int my_printf (void *my_object, const char *my_format, ...) __attribute__ ((format (printf, 2, 3)));

使编译器检查参数在调用my_printf与printf类型的格式字符串参数my_format一致。

无论是__attribute__是在函数原型之前还是之后。

所以你的情况,你可以做这样的事情:

class LoggingManager { 
    ... 
public: 
    void log(int32_t logLevel, const char *p_str, ...) __attribute__((format (printf, 3, 4))); 
    ... 
}; 

注意,因为这是你需要考虑通过隐性this参数的成员函数。所以格式字符串实际上是第三个参数而不是第二个参数。 (format (printf, 3, 4)而不是format (printf, 2, 3)

看到它的工作here

+0

请注意[Clang也支持这个](https://clang.llvm.org/docs/AttributeReference.html#format-gnu-格式)。 –

+0

@DanielH谢谢!更新了我的答案。 – Kevin

+0

谢谢!这是非常美丽的奖励点,以向我展示如何在我的成员函数中使用它! :) – keyboard

0

如果您正在使用Visual Studio,您可以使用SAL annotation_Printf_format_string_宏:

#include <sal.h> 

void log 
(
    int32_t         log_level 
, _In_z_ _Printf_format_string_ const char * psz_format 
, ... 
); 

为了使代码的可移植性,你可能要定义的格式属性宏观和SAL宏替换时需要:

#if defined(__GNUC__) 
#define ATTRIBUTE_PRINTF(format_index, vargs_index) __attribute__((__format__ (__printf__, format_index, vargs_index))) 
#else 
#define ATTRIBUTE_PRINTF(format_index, vargs_index) 
#endif 

#if defined(_MSC_VER) 
#include <sal.h> 
#else 
#define _In_z_ 
#define _Printf_format_string_ 
#endif 

void log 
(
    int32_t         log_level 
, _In_z_ _Printf_format_string_ const char * psz_format 
, ... 
) ATTRIBUTE_PRINTF(2, 3);