[英]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.