C ++ varargs包装器用于snprintf函数的意外行为

时间:2014-01-29 20:29:47

标签: c++ variadic-functions

我正在尝试使用char * ptr创建一个可以使用自动分配打印数据的类。

class String 
{
    char* data;
    size_t size;
    int pos;
    void init(size_t size)
    {
        this->size = size;
        data = new char[this->size+1];

        data[0] = 0;
        pos = 0;
    }

public:

String(size_t size=1)
{
    init(size);
}
    ...

    void show();
    void s_printf(char *format, ...);
}

我有分配,raii东西一切正常。 但是我的包装函数不会按照我想要的方式处理变量参数。据我所知,我正在使用va_list,va_start,va_end,但这似乎还不够。

代码:

void sprintf(char *format, ...)
{
    va_list args;
    va_start (args, format);

    int c = vsnprintf(&data[pos],size-pos,format,args);

    // this value is different on windows and linux (or msvc and gcc)
    if((c == -1) || (c > (size-pos)))
    {
        this->size *= 2;

        data = (char*)realloc(data,this->size);

        this->sprintf(format,args);
    }
    else
    {
        pos += c;
        data[pos] = 0;
    }

    va_end (args);

    return;
}

重新分配,处理变量“pos”和“size”,一切正常。但格式错误:

示例:

String x;

x.sprintf("thing %d, ",123);
x.sprintf("other thing");

x.show();

在Windows上打印:

  事情5698652,其他事情

在linux上,同样的事情,有时,从我的测试来看,“其他东西”指针值甚至被用作“东西%d”中的第一个“%d”(因此它打印“thing address < / em>,“)其中address是char *”other thing“的地址

1 个答案:

答案 0 :(得分:1)

由于您无法重复使用va_list,因此您应该重新创建它以重复打印:

void sprintf(char *format, ...)
{
  while(true)
  {
    va_list args;
    va_start (args, format);

    int c = vsnprintf(&data[pos],size-pos,format,args);

    va_end (args);

    // this value is different on windows and linux (or msvc and gcc)
    if((c == -1) || (c > (size-pos)))
    {
        this->size *= 2;
        data = (char*)realloc(data,this->size);
        continue;
    }
    else
    {
        pos += c;
        data[pos] = 0;
    }
    return;
  }
}