[英]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()
的參數的問題外 ,至少還有一些不太正確的事情,即使並非所有這些都會導致缺陷:
DWORD
也是32位。 保留21個字符以對其進行格式化是有點過大了,但不是錯誤。 但是,這表明可能會導致其他問題的誤解。 DWORD
是無符號類型,因此使用“%d”格式化它不是很正確 不,這是不正確的。 正確的代碼應如下所示:
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.