我正在编写一个使用C库的C++程序。这个C库有一个日志系统,其核心是一个类似于下面的宏定义:
如你所见,宏的第一个参数只能是字符串字面量,因为展开时会将这两个字面量拼接在一起。以下的写法是不可行的:
我想写一个函数来封装一些重复的工作(检查错误代码,如果有错误,则记录并抛出)。但是我无法得到比下面更好的东西:
但是这有一些问题:它人为地限制了错误消息的大小,并且
#define MACRO(s, ...) printf("log: " s "\n", ##__VA_ARGS__)
// supposed to be called like:
MACRO("network error %d", errno)
如你所见,宏的第一个参数只能是字符串字面量,因为展开时会将这两个字面量拼接在一起。以下的写法是不可行的:
char msg[] = "network error %d";
MACRO(msg, errno); // syntax error!
我想写一个函数来封装一些重复的工作(检查错误代码,如果有错误,则记录并抛出)。但是我无法得到比下面更好的东西:
#include <stdexcept>
#include <cstdarg>
#include <cstdio>
void throw_on_err(err_t err, const char *format...) {
if (err != OK) {
char buffer[128];
va_list args;
va_start(args, format);
vsnprintf(buffer, sizeof(buffer), format, args);
va_end(args);
MACRO("%s", buffer);
throw std::runtime_error(buffer);
}
}
// supposed to be called like:
throw_on_err(errno, "network error");
但是这有一些问题:它人为地限制了错误消息的大小,并且
(vsn)printf
的工作被执行了两次。
现在,我知道我可以用宏替换throw_on_err
,但我想避免这种解决方案:它更难调试,类型安全性较差。我想使用库的宏,因为它是标准的,并且比我展示的内容做更多的工作(这些工作与手头的问题无关,比如给输出添加颜色、检查日志级别等)。我尝试过使用const char*
参数、constexpr
函数来操作,但没有成功。
char buffer[128]
简直就是在寻找缓冲区溢出的问题... 将它改为至少char buffer[1000]
。你在节省栈内存方面并不会获得太多好处。 - selbie