我想使用内置的编译器检查来验证自定义日志框架的格式字符串,以捕获由于格式字符串不匹配而导致的奇怪的运行时崩溃<->
自定义c++日志方法的参数与printf()
系列相同,因此我试图替换所有对
MyLogger::Error(
fprintf(stderr,
虽然不幸的是(clang)预处理器阻塞了作用域解析运算符(::
),即只识别ULog
子字符串而不是ULog::Warn(
:
#define MyLogger::Error( fprintf(stderr,
任何关于如何完成这项工作的建议都非常感谢。
您尝试过可变模板吗?在这里找到。
#include <iostream>
namespace MyLogger
{
template <typename... T>
auto Error(const char * _Format, T &&... args)
{
return printf(_Format, std::forward<T>(args)...);
};
}
#define printf(...) MyLogger::Error(__VA_ARGS__)
int main()
{
MyLogger::Error("Non-Macro Print n");
printf("Macro Print n");
return 0;
}
根据@Someprogrammerdude建议的方法,我扩展了自定义日志类,使用clang/gcc格式属性以启用编译器格式检查。
声明变成
static void Error(const char *format,...) __attribute__ ((format (printf, 1, 2)));
使用预处理器通过调用printf()
来替换对自定义格式化程序的调用来临时启用检查,这比最初的想法更好,因为它始终能够立即捕获参数不匹配!
(FWIW -已经修复了我们120+ LOC代码库中的数十个问题和几个潜在的崩溃)
如果将MyLogger::Error
修改为
MyLogger::Error(args){
if (0) {
fprintf(stderr,args)
}
//actual function
}
这样可以得到内置的警告,并且不会影响代码的效率。(如果你想写错误的话,你可以使用print,但我想如果你想的话,你已经用过了)