1
\$\begingroup\$

I am using c++17 and wide characters.

I have created a function to create a wchar_t* using a variable number of parameters ...

#include <stdarg.h>

// the caller will free the memory
wchar_t* GetMessage( const wchar_t* format, ... )
{
  va_list args;
  va_start(args, format);

  // get the size of the final string
  const auto size = vswprintf(nullptr, 0, format, args);  

  // create the buffer
  const auto buffSize = size + 1;
  const auto buffer = new wchar_t[buffSize];
  memset(buffer, 0, buffSize * sizeof(wchar_t) );

  // create the string
  vswprintf_s(buffer, buffSize, format, args);
  
  va_end(args);

  // all done
  return buffer;
}

Can you suggest a more efficient, standard, way of achieving the above?

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

The code you have written is fine, apart from three small issues:

  1. You need to check that format isn't null before calling vswprintf otherwise it crashes.
  2. There seems to be the potential for memory leaking, you are assuming the caller will always release the memory. It would return a std::wstring instead, no need to new the buffer and it is "automatically" released.
  3. Check the results of vswprintf_s() it will almost never fail, but when it does you'll be trying to track down what went wrong for days. :)

This is my version:

// the caller will free the memory
std::wstring getMessage(const wchar_t* format, ...)
{
    std::wstring output;                                            // function return value.
    if (format != nullptr)
    {
        va_list args;
        va_start(args, format);
        const auto size = vswprintf(nullptr, 0, format, args);      // get the size of the final string
        if (size > 0)                                               // If the above call worked
        {   
            const auto buffSize = 1 + size;
            output.reserve(buffSize);                               // create the buffer
            if (vswprintf_s(output.data, buffSize, format, args) < 0)// create the string
            {
                output.clear();                                     // Empty the string if there is a problem
            }
        }
        va_end(args);
    }
    return output;
}
\$\endgroup\$
2
  • \$\begingroup\$ Thanks for the review, I like your suggestions, I wonder if there is any measurable performance difference in using std::wstring vs new wchar_t \$\endgroup\$
    – FFMG
    Jun 17, 2020 at 15:12
  • \$\begingroup\$ I would guess it would be worse, but safer. By coding wchar_t safely it would probably be slower. It depends on which is more important. \$\endgroup\$ Jun 18, 2020 at 7:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.