I am going through a previously written code and I found StringCbPrintf()
function
I found declaration on msdn
site like this :
HRESULT StringCbPrintf(
_Out_ LPTSTR pszDest,
_In_ size_t cbDest,
_In_ LPCTSTR pszFormat,
_In_ ...
);
What is _in_
and _out_
here ?
And why is it needed when we already have sprintf()
?
_In_
and _Out_
(note: neither _in_/_out
_ as you wrote, nor __In__/__Out__
with double underscores, as written in some other answer) are so called SAL Annotations. They can be used with /analyze
compiler option, and can help identify bugs and problems like buffer overruns etc. with raw C buffers and pointers. In addition to MSDN documentation on SAL, you can read also this blog post.
Someone ironically (and wrongly) wrote that:
"In the rest of the world, inputs are const pointers but I guess that was too simple. :)"
missing the fact that SAL is more powerful than that. In fact, with SAL you can also specify the maximum size of a destination buffer, indicating which parameter contains the destination buffer size; e.g. if you open <strsafe.h>
header, you can read that the actual SAL annotations used for StringCbPrintfW
(the Unicode version of StringCbPrintf
) is something like that:
STRSAFEAPI
StringCbPrintfW(
__out_bcount(cbDest) STRSAFE_LPWSTR pszDest,
__in size_t cbDest,
__in __format_string STRSAFE_LPCWSTR pszFormat,
...)
{
....
Note how the __out_bcount(cbDest)
SAL annotation applied to the pszDest
parameter specifies that this is a pointer to an output buffer (__out
), which size is expressed in bytes (_bcount
) by the parameter cbDest
. As you can see, this is a rich annotation (richer than simple "const
" or "non const
").
In my opinion, SAL is kind of useless if you write C++ code with robust container classes like std::vector
or std::string
, which know their own size, etc. But SAL can be useful in C-ish code with raw pointers (like several Win32 APIs).
About the second part of your question:
"Why we need
StringCbPrintf
if we already havesprintf
"
the main reason is that sprintf
is an unsafe and buffer overruns-prone function; instead with StringCbPrintf
you must specify the maximum size of the destination buffer, and this can help preventing buffer overruns (which are security enemies).
The documentation tries to explain that for you:
Compared to the functions it replaces, StringCbPrintf provides additional processing for proper buffer handling in your code. Poor buffer handling is implicated in many security issues that involve buffer overruns. StringCbPrintf always null-terminates a nonzero-length destination buffer.
The __In__
and __Out__
decorators are used in Microsoft API:s to denote how a pointer argument is used. In the rest of the world, inputs are const
pointers but I guess that was too simple. :)
As it is said here:
StringCbPrintf is a replacement for the following functions:
- sprintf, swprintf, _stprintf
- wsprintf
- wnsprintf
- _snprintf, _snwprintf, _sntprintf
So it doesn't only replace sprintf
, but also those to work with wchar
, for example. It also introduces additional buffer processing to prevent buffer overruns (as stated in the same msdn article). It also always null-terminates the destination buffer. _in_
and _out_
are there to show you which parameters are input ones, and which are output ones. Those are most likely #define
d as nothing, and go away before the compilation begins.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With