Reputation: 343
While implementing a simple printf style logger I encountered a vsnprintf crash. This is how I call the logger utility:
LoggerUtil->LogInfo("Whatever info here %s", "just a test!");
It calls a function with a variable number of arguments. The idea is to add extra information to the format string so I need to change 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 :(
...
}
Can't figure out the main problem, not tempering with fmt solves the problem but it's not an option:
void LoggerUtil::LogInfo(const char* fmt, ...)
{
va_list arg_list;
va_start(arg_list, fmt);
Logger::InfoVA(fmt, arg_list);
va_end(arg_list);
}
What am I missing here?
Upvotes: 0
Views: 1577
Reputation: 597166
After using LogClientInfo()
to create a new format string, you are then passing the wrong input value to the second parameter to va_start()
. You are passing your local format
variable, but you need to pass the fmt
argument of LogInfo()
instead. Just because you are using a different format string when calling Logger::InfoVA()
does not change where the input format values are stored. va_start()
configures the va_list
to point at the next function argument relative to the specified argument, and in this case that needs to be the fmt
function argument, not the local format
variable:
void LoggerUtil::LogInfo(const char* fmt, ...)
{
std::string formatStr = LogClientInfo(fmt);
va_list arg_list;
va_start(arg_list, fmt); // <-- use fmt here !
Logger::InfoVA(formatStr.c_str(), arg_list);
va_end(arg_list);
}
Upvotes: 2