[英]Is this correct size to buffer?
Is this the right size to hold a integer value on 64-bit machine plus a unicode string? 这是在64位计算机上容纳整数值和Unicode字符串的正确大小吗? 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: 除了Kirill Kobelev的答案中提到的传递给
swsprintf_s()
的参数的问题外 ,至少还有一些不太正确的事情,即使并非所有这些都会导致缺陷:
DWORD
in the Windows SDK is 32-bits, even when building for a 64-bit target. DWORD
也是32位。 Reserving 21 characters for formatting it is a small bit of overkill, but not a bug. DWORD
is an unsigned type, so using "%d" to format it isn't quite right DWORD
是无符号类型,因此使用“%d”格式化它不是很正确 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. 您调用
MessageBox()
函数是正确的。
Manually calculating the required buffer size for the destination of an sprintf
call is difficult to maintain. 手动维护
sprintf
调用目标所需的缓冲区大小很难维护。 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. Visual Studio附带的CRT为此提供了
_scprintf
系列功能。
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. 此函数返回一个
std::wstring
对象。 Just like the std::vector
used in the implementation, it automatically manages memory for you, and no explicit cleanup code is required. 就像实现中使用的
std::vector
一样,它会自动为您管理内存,不需要显式的清理代码。 To use it with Windows API calls that require an LPCWSTR
argument call its c_str()
member. 要将其与需要
LPCWSTR
参数的Windows API调用一起使用,请调用其c_str()
成员。
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);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.