简单记录器类vsnprintf因读取访问冲突而崩溃

时间:2016-12-15 19:52:47

标签: c++ crash printf

在实现一个简单的printf样式记录器时遇到了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);
}

我在这里缺少什么?

1 个答案:

答案 0 :(得分:2)

使用LogClientInfo()创建新的格式字符串后,您将错误的输入值传递给第二个参数va_start()。您正在传递本地format变量,但您需要传递fmt LogInfo()参数。仅仅因为在调用Logger::InfoVA()时使用不同的格式字符串不会改变存储输入格式值的位置。 va_start()va_list配置为指向相对于指定参数的下一个函数参数,在这种情况下,需要是fmt函数参数,而不是本地format变量:

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);
}