我目前有一个日志记录解决方案,它定义了如下宏:
#define MY_LOG(level, component, message, ...) { MyLog::Instance()->Log(level, component, message, __FILE__, __LINE__, ##__VA_ARGS__); }
const char*消息参数使用类似printf的格式,如“我的名字是%s,我是%u”
我使用的实际日志记录方法是在堆栈上声明一个char buffer[2048]变量,并使用vsnprintf将消息参数中定义的va_list参数转换为缓冲区。然而,由于我经常处理的值可能大于2K,所以我的缓冲区总是被截断,所以我想到了围绕SrrSnWrand的整个事情,这将更加灵活。
在实现此解决方案时,我在从列表中检索要与<我不能使用外部LIBS,因为我支持可能或可能不支持C++ 11的平台和编译器,我不能完全依赖于新的语言特征,但是添加定义来支持这两种实现是可行的。另外,由于大量的跟踪已经在当前的代码库中,所以我无法真正更改消息格式。
谢谢!
最佳答案
我建议不要尝试在stringstream上重新实现vsnprintf。如果你想保持你的日志前端不变,你应该保持vsnprintf!
首先,您应该更确切地猜测格式化字符串的最终大小并分配一些缓冲区(如果您喜欢的话,使用C++ 11 UnQuyjpTR)。您不应该害怕分配开销,因为这基本上就是stringstring在引擎盖下所做的事情。
然后,用这个缓冲区调用vsnprintf并测试它的返回值。此值(如果为正值)将为您提供正确格式化输出字符串(不包括终止的空字符)所需的最小大小。知道了这一点,您可以选择重新分配一些大小正确的缓冲区,并用它再次调用vsnprintf。
最后,对这个格式化字符串执行任何操作:
-构造std::字符串
-把它写在某处(文件里?)
-别忘了释放内存(或使用unique-ptr)。
注意:不要直接使用std::string作为缓冲区。写入std::string::c_str()返回的缓冲区是未定义的行为。