sprintf_s() are additions to VC++8, and were supposedly written to tolerate formatting errors and to avoid buffer overruns. They differ from their corresponding non-safe cousins
sprintf() by taking an extra argument (the 2nd parameter), which is the size of the buffer passed as the first argument. The prototype for
int swprintf_s(wchar_t *Buf, size_t sizeOfBuf, const wchar_t *format [, argument]...)
The following use of
would seem to be in keeping with the prototype declaration.
swprintf_s(buf, sizeof buf, "%s%d", L"result", 2);
However, this code is likely to cause a crash in the next few statements following it, but not always.
If you change the code to
swprintf_s(buf, 12, "%s%d", L"result", 2);
it will correctly execute.
A close examination of the documentation reveals that the 2nd parameter is not a size, in spite of its type, but instead the number of characters in the buffer. The reason the first example crashes is because
sizeof(wchar_t) is greater than 1. If we assume
sizeof(wchar_t) == 2, then
sizeof buf == 24, but since the 2nd argument is taken as the number of characters
swprintf_s() thinks that it has a 48 byte memory area. So what? The format request only generates 8 characters. However, if you watch the memory area (with VS8) passed as the 1st parameter while
swprintf_s() executes, you will see the Debug version clear to uninitialized all the bytes in the buffer beyond those in which it writes the formatted information. So if you pass the wrong size to
swprintf_s(), it will spank you by overwriting your data.
The poor aspect of this design is avoidance of
sizeof, which is the standard C/C++ operator for compile-time determination of memory sizes. Even though the type of the 2nd parameter would imply a
sizeof value, this is not what the function expects.
sizeof is the language's way of keeping byte counts out of a program, but
swprintf_s()'s design forces character counts back into the program. Consider what would happen if the buffer size is changed. Is the programmer going to realize that all the character count arguments to
swprintf_s() calls also need to be changed?
In order to be truly safe, the 2nd parameter needs to be coded as:
(sizeof buf)/(sizeof buf)
We divide the size of an array by the size of an array element, which provides the number of array elements. This is the expression that is needed as the 2nd parameter to
in order to keep your code independent of changes to the size of the buffer. Microsoft has incorporated this definition in the
macro, which is not standard C, but is available in VS8
As to why the function spends CPU time clearing the remaining buffer, I guess that it is an attempt to generate a quick failure if the wrong the size passed. I hope that this undocumented feature is only in the Debug version of the function.