C++ C++;添加错误使用自定义打印/日志函数的编译器警告
我有以下功能,我希望在使用printf时有警告:C++ C++;添加错误使用自定义打印/日志函数的编译器警告,c++,printing,format,compiler-warnings,C++,Printing,Format,Compiler Warnings,我有以下功能,我希望在使用printf时有警告: 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); inte
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);
}
如果我忘记在格式字符串中为其中一个标记添加参数,我希望以某种方式得到警告。此外,警告过多(或错误的论点)也会很可怕。
由于忘记了日志函数中的一个参数,我最近遇到了一些崩溃
如果不可能这样做,我如何重写我的函数,使其具有警告但具有相同的功能?如果您使用的是gcc/g++/clang,那么您可以使用上指定的格式属性: 格式(原型、字符串索引、首先检查) format属性指定函数接受printf、scanf、strftime或strfmon样式的参数,这些参数应根据格式字符串进行类型检查。例如,宣言:
extern int my_printf(void*my_对象,const char*my_格式,…)
__属性(格式(printf,2,3))代码>
使编译器检查调用my_printf时的参数与printf样式格式字符串参数my_format的一致性
\uu属性是在函数原型之前还是之后并不重要
因此,在您的情况下,您可以这样做:
class LoggingManager {
...
public:
void log(int32_t logLevel, const char *p_str, ...) __attribute__((format (printf, 3, 4)));
...
};
请注意,因为这是一个成员函数,所以您需要考虑传递的隐式this
参数。所以格式字符串实际上是第三个参数,而不是第二个。(格式(printf,3,4)
而不是格式(printf,2,3)
)
查看它的工作情况。如果您使用的是Visual Studio,则可以使用\u Printf\u format\u string\u
宏:
#include <sal.h>
void log
(
int32_t log_level
, _In_z_ _Printf_format_string_ const char * psz_format
, ...
);
#包括
空位日志
(
int32\u t日志级别
,_In_z__打印格式_字符串uu常量字符*psz_格式
, ...
);
要使代码可移植,可能需要在必要时定义格式属性宏和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);
#如果已定义(uu GNUC_uu)
#定义属性(格式索引,变量索引)属性(格式索引,变量索引)
#否则
#定义属性(格式索引、变量索引)
#恩迪夫
#如果已定义(\u MSC\u VER)
#包括
#否则
#在z中定义_
#定义打印格式字符串_
#恩迪夫
空位日志
(
int32\u t日志级别
,_In_z__打印格式_字符串uu常量字符*psz_格式
, ...
)属性_PRINTF(2,3);
请注意。@DanielH谢谢!更新我的答案。谢谢!这是非常漂亮的,并且为我展示了如何在我的成员函数中使用它而获得了额外的积分!:)请不要用c标记,这不是有效的c代码。对我不起作用。如果我用Printf_format_string声明我自己的函数,我不会得到任何警告,如果我使用标准的sprintf,一切都正常。VS2017 15.9.7,包括在内。有什么想法吗?@ GeoGeHAZAN可能警告被禁止或C++代码分析不执行。当我用PrtTF替换自己的函数而不改变任何其他东西时,警告就存在,所以这不是问题,我在短片段中总结了这个问题: