1

I have a wrapper function that allows me to achieve the result of sprintf by writing one line of code instead of 3.

void output(const tstring& format, ...)
{
    va_list args;
    va_start(args, format);

    const int len = _vsctprintf(format.c_str(), args) + 1;
    TCHAR* buf = new TCHAR[len];

    _vstprintf(buf, format.c_str(), args);
    OutputDebugString(buf);

    delete[] buf;
}

My problem: The variadic arguments are corrupted.

For example;

output(_T("%d\n"), 1); // outputs: -858993460
output(_T("%d\n"), 2); // outputs: -858993460

Whats the cause of this error and how can I fix it?

sazr
  • 24,984
  • 66
  • 194
  • 362
  • If you make `format` not a reference, does the problem stop occurring? – user253751 Apr 27 '16 at 05:28
  • Note that with c++11 and variadic template, you may do `template void outout(const tstring& format, Ts...args) { const int len = _vsctprintf(format.c_str(), args...); std::vector buf(len); _vstprintf(buf.data(), format.c_str(), args...); OutputDebugString(buf.data()); }`. – Jarod42 Apr 27 '16 at 08:19

1 Answers1

4

According to the C++ standard [support.runtime], when discussing the second parameter to va_start:

The parameter parmN is the identifier of the rightmost parameter in the variable parameter list of the function definition (the one just before the ...). If the parameter parmN is of a reference type, or of a type that is not compatible with the type that results when passing an argument for which there is no parameter, the behavior is undefined.

Emphasis mine. Your format parameter is a reference type, hence its use as the last parameter before the ... results in undefined behavior.

Raymond Chen
  • 44,448
  • 11
  • 96
  • 135