C++ - 移植 Linux 代码 - _vscprintf返回错误数量的参数

C++ - porting linux code - _vscprintf returns wrong number of arguments

本文关键字:错误 参数 返回 vscprintf 移植 Linux 代码 C++      更新时间:2023-10-16

不久前,我在linux下编写了一个记录器类,我尝试将其移植到Windows(Visual Studio)下,但它一直崩溃

首先我不得不使用vsprintf的vsprintf_s,因为comiler拒绝了它

但我找到的唯一例子似乎不起作用

"len"内容错误的值而不是实际数量的参数

这是我调用函数的方式:

Logger::print("Rock and roll");

Logger::print("%4.2f %4.2f %4.2f %4.2f %4.2f %4.2f %4.2f %4.2fn", a.x, a.y, b.x, b.y, c.x, c.y, d.x, d.y);

原始 Linux 代码:

void Logger::print(const std::string fmt,...)
{
    char formatted_string[2*1024];
    strcpy(formatted_string,this->prefix);
    strcat(formatted_string,"  ");
    char*strPtr=&formatted_string[0]+strlen(this->prefix)+1;
    va_list argptr;
    va_start(argptr, fmt );
    vsprintf(strPtr,fmt.c_str(), argptr);
    va_end(argptr);
    printf("%sn",formatted_string);
}         

新窗口代码:

void Logger::print(const std::string fmt, ...)
{
    va_list args;
    int len;
    char * buffer;
    va_start(args, fmt);
    len = _vscprintf(fmt.c_str(), args); << len contents odd values instead of real number of arguments
    va_end(args);
    buffer = (char*)malloc(len * sizeof(char));
    vsprintf_s(buffer, len, fmt.c_str(), args);
    Logger::file << buffer;
    free(buffer);
}

问候

您过早

地调用了va_end 。解决此问题,您也没有计算正确的目标大小,因为_vscprintf不包括vsprintf_s将使用的终止空字符的空间。

函数的主体应如下所示,包括删除该malloc调用以支持使用向量的正确 RAII 解决方案:

va_list args;
va_start(args, fmt);
int len = _vscprintf(fmt.c_str(), args);
if (len > 0)
{
    std::vector<char> buff(len + 1); // include terminator space
    vsprintf_s(&buff[0], buff.size(), fmt.c_str(), args);
    Logger::file << buff.data();
}
va_end(args);

值得注意的是:在调试器中运行原始代码将导致缓冲区太小的异常,调试器将轻松捕获该异常。调试器是晚餐。

这里是工作代码

void Logger::print(const std::string fmt, ...)
{
    va_list args;
    int len;
    char * buffer;
    va_start(args, fmt);
    len = _vscprintf(fmt.c_str(), args)+1;
    buffer = (char*)malloc(len * sizeof(char));
    vsprintf_s(buffer, len, fmt.c_str(), args);
    va_end(args);
    Logger::file << buffer;
    free(buffer);
}