简体   繁体   中英

Is this correct size to buffer?

Is this the right size to hold a integer value on 64-bit machine plus a unicode string? or am I missing something?

    DWORD errorMessageID = GetLastError();
        const wchar_t msgFmt[] = L"foo baaa. Error code = %d";
        wchar_t bufferMsg[sizeof(msgFmt) +        // room for fmt message string itself
            21 +  // enough to hold numbers up to 64-bits
            sizeof(wchar_t)         // byte-terminattor
        ];
        int nBytesWritten = swprintf_s(bufferMsg,
            msgFmt,
            sizeof(msgFmt),
            errorMessageID);

        MessageBox(NULL, 
                    bufferMsg,
                    TEXT("Copy to clipboard failed"), 
                    MB_OK | MB_ICONERROR);

In addition to the problems with the arguments passed to swsprintf_s() mentioned in Kirill Kobelev's answer , there are at least a few more things that aren't quite right, even if not all of them would result in a defect:

  • a DWORD in the Windows SDK is 32-bits, even when building for a 64-bit target. Reserving 21 characters for formatting it is a small bit of overkill, but not a bug. However, it's an indication of a misunderstanding that might result in other problems.
  • DWORD is an unsigned type, so using "%d" to format it isn't quite right
  • if you were going to format a 64-bit signed int, "%d" would still be the wrong format spec to use, since it indicates that the argument is a 32-bit int type. You would want to use something like "%lld" or "%I64d" to format a 64-bit int type.

No, this is not correct. The right code should look like:

const wchar_t msgFmt[] = L"foo baaa. Error code = %d";
wchar_t bufferMsg[sizeof(msgFmt)/sizeof(wchar_t) + // room for fmt message string itself
    21 +      // enough to hold numbers up to 64-bits
    1         // symbol-terminator
];
int nBytesWritten = swprintf_s(bufferMsg,
    sizeof(bufferMsg)/sizeof(wchar_t),
    msgFmt,
    errorMessageID);

In both cases you used the byte-size instead of the number of elements plus the order of params is wrong. You call of the MessageBox() function is correct.

Manually calculating the required buffer size for the destination of an sprintf call is difficult to maintain. It is easier and safer to have the system perform the calculation for you. The CRT that ships with Visual Studio provides the _scprintf family of functions for this.

The following code illustrates its usage. It implements a function that takes a format string and a variable number of arguments and returns a string that is the result of formatting:

std::wstring FormatString( const wchar_t* a_Format, ... ) {
    std::wstring text;
    va_list argList;
    va_start( argList, a_Format );
    // Calculate required buffer size
    size_t size = _vscwprintf( a_Format, argList ) + 1;
    va_end( argList );
    if ( size > 0 ) {
        // Dynamically construct buffer with the correct size
        std::vector<wchar_t> buffer( size );
        va_start( argList, a_Format );
        int count = _vsnwprintf_s( buffer.data(), size, size - 1,
                                   a_Format, argList );
        va_end( argList );
        if ( count >= 0 ) {
            // Construct return value
            text = std::wstring( buffer.data(), count + 1 );
        }
    }
    return text;
}

This function returns a std::wstring object. Just like the std::vector used in the implementation, it automatically manages memory for you, and no explicit cleanup code is required. To use it with Windows API calls that require an LPCWSTR argument call its c_str() member.

Using this function in your original code condenses it down to the following:

DWORD errorMessageID = GetLastError();
MessageBoxW(NULL,
            FormatString( L"foo baaa. Error code = %u", errorMessageID ).c_str(),
            L"Copy to clipboard failed",
            MB_OK | MB_ICONERROR);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM