如何计算格式化wchar数组所需的大小,`CRT_SECURE`方式?

时间:2017-07-17 10:43:38

标签: c++ format wchar-t

我需要计算格式化wchar数组的大小 请考虑以下代码:

wchar_t* Format(const wchar_t* format, ...)
{
    va_list args;
    va_start(args, format);

    wchar_t *w = NULL;
    int len = _vsnwprintf(NULL, 0, format, args) + 1;            // <------ Error
    if (len > 0)
    {
        w = new wchar_t[len];
        w[0] = 0;
        _vsnwprintf_s(w, len, len, format, args);
    }
    va_end(args);

    return w;
}

如果启用_CRT_SECURE_NO_WARNINGS,则代码工作以上,如果没有,则错误说:

  

'_ vsnwprintf':此函数或变量可能不安全。考虑使用   改为_vsnwprintf_s。

但我无法使用_vsnwprintf_s来计算wchar缓冲区所需的大小。

以下是我的尝试:

int len = _vsnwprintf_s(NULL, 0, 0, format, args); // return 1

// debug assertion failed: string != NULL && DstSizeInWords > 0
int len = _vsnwprintf_s(NULL, 0, INT_MAX, format, args);

// debug assertion failed: string != NULL && DstSizeInWords > 0
int len = _vsnwprintf_s(NULL, INT_MAX, 0, format, args);

// debug assertion failed: string != NULL && DstSizeInWords > 0
int len = _vsnwprintf_s(NULL, INT_MAX, INT_MAX, format, args);

其他功能:_snwprintf给出_CRT_SECURE错误,_snwprintf_s_vsnwprintf_s

有相同的效果

问题:

虽然开启_CRT_SECURE_NO_WARNINGS后我还不错,但我想知道如何计算格式化wchar数组CRT_SECURE方式所需的大小?请注意,它必须接受va_list作为agrument。

1 个答案:

答案 0 :(得分:1)

您应该能够使用_vscwprintf获取所需的缓冲区大小:

_Check_return_ _Ret_z_ wchar_t *
Format(_Printf_format_string_ _In_z_ wchar_t const * const psz_format, ...)
{
    size_t formatted_string_length;
    va_list args;
    {
        va_start(args, psz_format);
        int const result(::_vscwprintf(psz_format, args));
        va_end(args);
        if(-1 == result)
        {
            ::abort();
        }
        assert(0 <= result);
        formatted_string_length = static_cast< size_t >(result);
    }
    size_t const buffer_size(formatted_string_length + 1u);
    wchar_t * const p_buffer(new wchar_t[buffer_size]);
    {
        va_start(args, psz_format);
        int const result(::_vsnwprintf_s(p_buffer, buffer_size, formatted_string_length, psz_format, args));
        va_end(args);
        if(-1 == result)
        {
            ::abort();
        }
        assert(0 <= result);
        assert(static_cast< size_t >(result) == formatted_string_length);
        assert(L'\0' == p_buffer[formatted_string_length]);
    }
    return p_buffer;
}