簡體   English   中英

這是要緩沖的正確大小嗎?

[英]Is this correct size to buffer?

這是在64位計算機上容納整數值和Unicode字符串的正確大小嗎? 還是我錯過了什么?

    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);

除了Kirill Kobelev的答案中提到的傳遞給swsprintf_s()的參數的問題外 ,至少還有一些不太正確的事情,即使並非所有這些都會導致缺陷:

  • 即使為64位目標構建時,Windows SDK中的DWORD也是32位。 保留21個字符以對其進行格式化是有點過大了,但不是錯誤。 但是,這表明可能會導致其他問題的誤解。
  • DWORD是無符號類型,因此使用“%d”格式化它不是很正確
  • 如果要格式化64位帶符號的int格式,則“%d”仍然是使用錯誤的格式規范,因為它表明該參數是32位int類型。 您可能想使用“%lld”或“%I64d”之類的格式來格式化64位int類型。

不,這是不正確的。 正確的代碼應如下所示:

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);

在這兩種情況下,都使用字節大小而不是元素數量加上參數順序是錯誤的。 您調用MessageBox()函數是正確的。

手動維護sprintf調用目標所需的緩沖區大小很難維護。 讓系統為您執行計算更加容易和安全。 Visual Studio附帶的CRT為此提供了_scprintf系列功能。

以下代碼說明了其用法。 它實現了一個函數,該函數采用格式字符串和可變數量的參數,並返回作為格式化結果的字符串:

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;
}

此函數返回一個std::wstring對象。 就像實現中使用的std::vector一樣,它會自動為您管理內存,不需要顯式的清理代碼。 要將其與需要LPCWSTR參數的Windows API調用一起使用,請調用其c_str()成員。

在原始代碼中使用此功能可將其壓縮為以下內容:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM