在实现一个简单的printf样式记录器时,我遇到了一个vsnprintf崩溃。这就是我所说的记录器实用程序:简单记录器类vsnprintf崩溃与读取访问冲突
LoggerUtil->LogInfo("Whatever info here %s", "just a test!");
它调用具有可变数量参数的函数。我们的想法是多余的信息添加到格式字符串,所以我需要改变FMT:
std::string LoggerUtil::LogClientInfo(const char* fmt)
{
return "Some info here %s";
}
void LoggerUtil::LogInfo(const char* fmt, ...)
{
std::string formatStr = LogClientInfo(fmt); // returns "Some info here %s" just for testing altering the format string
const char* format = formatStr.c_str(); // checked memory and its '\0' terminated string
va_list arg_list;
va_start(arg_list, format);
Logger::InfoVA(format, arg_list);
va_end(arg_list);
}
void Logger::InfoVA(const char* fmt, va_list arg_list)
{
Log(Priority_Info, fmt, arg_list);
}
void Logger::Log(Priority priority, const char* fmt, va_list args)
{
char str[MaxLogEntrySize];
memset(str,0,MaxLogEntrySize*sizeof(char));
vsnprintf(str,MaxLogEntrySize-1, fmt, args); // CRASH :(
...
}
想不通的主要问题,而不是与FMT回火解决了这个问题,但它不是一个选项:
void LoggerUtil::LogInfo(const char* fmt, ...)
{
va_list arg_list;
va_start(arg_list, fmt);
Logger::InfoVA(fmt, arg_list);
va_end(arg_list);
}
我在这里错过了什么?
我没有立即看到一个问题。使用内存检测工具(如purify或valgrind)来搜索内存损坏。仅仅因为一个C++程序崩溃在一个特定的功能并不意味着这是错误的地方。 –
'va_start(arg_list,format);''我想它应该是'va_start(arg_list,fmt);''除非你试图做一些棘手的事情,我无法得到。但基本上你在其他地方兜售'va_start',UB。我没有发布这个答案,因为我不确定它是否修复了代码中的所有可能的问题。 –
由于您使用'C++',因此有更好的方法来实现可变数量的参数,例如使用[变量参数模板](http://en.cppreference.com/w/cpp/language/parameter_pack)。然后,你不会与va_start,va_arg等混淆。请参阅链接中的示例代码。 – PaulMcKenzie