Why in msvc++ we have _snprintf while other compilers allows snprintf - c++

What "_" means? Why Microsoft adds this mark at the beginning?

Identifiers in the global namespace starting with _ are reserved for the implementation. _snprintf is just a function that the implementation (Visual Studio) has provided. As to the rationale for that, Visual Studio implements C89, and snprintf is part of a later C99 standard.
Besides that, the semantics of both functions are different in the return type, which in snprintf is always the number of characters that the formatted string takes (whether there was enough space in the buffer or not, while _snprintf will return a negative number if there is not enough space in the buffer.
That is, to allocate a buffer just large enough for the output you can do:
int size = snprintf( 0, 0, "%s %d\n", str, i );
char * buffer = malloc( size+1 );
snprintf( buffer, size+1, "%s %d\n", str, i );
You cannot do that with _snprintf as the only information that the function yields back is that the current size is not enough.

snprintf() was not yet part of the standard at the time Microsoft's C runtime began to support it.
Since the function prototype was not standardized, and the developers did not want to use the name snprintf (in case the standard later specified a different prototype), they opted to add a leading underscore to denote the function as being a Microsoft extension to the standard.

Adding to the above,
there are proper C99 snprintf() and vsnprintf() available since Visual Studio 2015
and they do not even trigger the well known unsafe function deprecation warning.
_snprintf_s() or _vsnprintf_s(), while provided, are "secure variants" of the MSVC-specific functions, with the non-C99 behavior.

Aside from a different return value in case of insufficiently large buffer (described in David's answer), functions from _sn... group differ from the standard snprintf in another important regard. If the target buffer is too short by just one character, the _sn... functions consider this situation a "success".
In more detail, if the target buffer is long enough to store the whole resultant sequence but without the terminating zero character, the _sn... functions do not truncate the result, do not write the terminating zero into the target buffer and return the size of the buffer as a result. So, in general case the result is not guaranteed to be zero-terminated.
In the same situation, snprintf will discard the last character of the resultant sequence and write zero terminator in its place. The result of snprintf is always zero-terminated.

Related

Why is strncpy marked as unsafe?

I am getting a warning:
warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead.
To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
F:\vuStudio\VC\include\string.h(188) : see declaration of 'strncpy'
I read on stackoverflow.com that strcpy is not safe and I should use strncpy instead. But now why I am getting warning that strncpy is unsafe ?
I am calling it as:
strncpy(this->title, title.c_str(), sizeof(this->title));
strncpy has a few dangerous quirks.
First, it zeros the target buffer past the end of the copy, which can be surprising.
Second, if there is not enough room in the target buffer, it does not null terminate the target buffer.
Third, if it truncates, it 'mostly works'. Which discourages error handling (truncated strings are often worse than useless, but do not appear to be worse than useless at first glance).
strncpy_s requires an input length (or explicit truncation request), and errors if there is not enough room to null terminate (writing just a zero length string in the output). The input length is sometimes inefficient to provide (and not required for some of its changes), but it does guarantee a null terminated output buffer (so long as it isn't a nullptr, or zero length) even in error conditions. I am unsure if it zeros past the end of the copied string or not.
This behavior prevents or mitigates some common fenceposting errors in string code.
Visual studio compiler has it's own implementation of strncpy, you won't get this warning with gcc or clang. It is safe, and more portable (because strncpy_s is not standard) to use strncpy.
If you don't care about portability, strncpy_s is indeed more secure because it has an additional length check (but like strncpy it won't save you if you pass bad parameter).
The "n" variants of str functions (like strncmp, strncpy, etc) are the "safe" choice, because they all are limiting the size of string buffer used.
The "old" str functions (not the "n" variants, like strcpy) are all subject to many programming errors and memory attacks (off by one, heap overwriting, etc).

How to implement in C++ crossplatform snprintf?

I wonder if it is possible and how to implement in C++ crossplatform, (C99, C++0x independent ) snprintf? Is there such in boost? (I wonder about what is the C++ idiom to replace snprintf(4)?)
std::ostringstream would be an alterntive to using snprintf:
char buf[1024];
snprintf(buf, 1024, "%d%s", 4, "hello");
Equivalent:
#include <sstream>
std::ostringstream s;
s << 4 << "hello";
// s.str().c_str(); // This returns `const char*` to constructed string.
There is also boost::lexical_cast:
std::string s = boost::lexical_cast<std::string>(4) +
boost::lexical_cast<std::string>("hello");
Yes, there is Boost Format library that supports formatting strings.
You might want to look at the Qt QString class, which provides a format function which does about what you want in a very OO sort of way. You could certainly copy and learn from it.
yes, it might be taboo to mention Qt in a question that was tagged boost, but the question seemed more generic than that.
Since Boost was mentionned, is there anything wrong with Boost.Format ?
Once I needed snprintf on Windows/Linux/HP-UX. I defined snprintf_safe and on Linux/HP-UX I made use of snprinf and on Windows I made use of _snprintf. I remember that _snprintf has a little bit different approach to writing '\0' if the number of bytes required to store the data exceeds the maximum allowed size. So It was necessary to handle. Anyway, it was this kind of macro:
#ifdef #WIN32
int snprintf_safe()
{
// make use of _snprintf
}
#else
#define snprintf_safe snprintf
#endif
std::ostringstream or std::to_string (c++11) works as an alternative, but if you require a better performance solution without extra copies or do only have C not C++ you might need to do something else:
MSVC does not support C99 and therefore has not snprintf function but only their selfmade:
_snprintf.
Differences between MSVCs _snprintf and official C99 (gcc,clang) snprintf:
Return value:
MSVC: return -1 if buffer size not enough to write everything (not including terminating null!)
GCC: return number of characters that would have been written if buffer large enough
Written bytes:
MSVC: write as much as possible, do not write NULL at end if no space left
GCC: write as much as possible, always write terminating NULL (exception: buffer_size=0)
Interesting %n subtlety:
If you use %n in your code, MSVC will leave it unitialized! if it it stops parsing because buffer size is to small, GCC will always write number of bytes which would have been written if buffer would have been large enough.
So my proposal would be to write your own wrapper function mysnprintf using vsnprintf / _vsnprintf which gives same return values and writes the same bytes on both platforms (be careful: %n is more difficult to fix).

SystemC error, using visual c++ 2008

I am using systemC with visual C++ 2008. I wrote a simple hello world program. However I am getting this error repeatedly:
warning C4996: 'sprintf': This function or variable may be unsafe.
Why this is happening? I would appreciate any help.
The compiler warns against sprintf() use because it may cause buffer overflow since it doesn't check buffer's limit. Instead, use snprintf() which never fills the buffer beyond the passed-in limit.
This advice is also given by the manpage:
Because sprintf() and vsprintf() assume an arbitrarily long string, callers must be
careful not to overflow the actual space; this is often impossible to assure. Note that
the length of the strings produced is locale-dependent and difficult to predict. Use
snprintf() and vsnprintf() instead (or asprintf(3) and vasprintf(3)).
It's insecure because - From MSDN
There is no way to limit the number of characters written, which means that code using sprintf is susceptible to buffer overruns. Consider using the related function _snprintf, which specifies a maximum number of characters to be written to buffer, or use _scprintf to determine how large a buffer is required. Also, ensure that format is not a user-defined string.

sizeof("...") in visual c++ makes me unhappy

I was writing a piece of code where I use sizeof("somestring") as a parameter of a function, then I noticed the function was not returning the expected value, so I went to see the corresponding asm code and I found an unpleasant surprise. Does anyone have an explanation for this (see the picture)?
I know there are 1000+ different ways of doing this, I already implemented another one of them, but I do want to know the reason behind this behaviour.
For the curious, this is Visual Studio 2008 SP1.
The value 5 is correct. The constant includes the zero terminator byte. The display of 4 in the watch window is the one that does not appear to be correct.
String literals are of type "array of n const char" ([lex.string], ¶8), where n is the number of chars of which the string is composed. Since the string is null-terminated, sizeof will return the number of "normal" characters plus 1; the watch window is wrong, it's probably a bug (as #Gene Bushuyev said, it's probably interpreting it as a pointer instead of as a literal=array).
The fact that the value 5 is embedded into the code is normal, being sizeof a compile-time operator.
there is a C-String terminator '\0' on the end of every C-String so "pdfa" is actually the following char array {'p', 'd', 'f', 'a', '\0'} but the \0 will not be printed. Use strlen("pdfa") instead.
Remember that C strings contain an ending zero \0. Five is the correct value.
Well, 5 is the correct value of sizeof("PDFA"). 4 characters + trailing zero.
Also, keep in mind, that "The result does not necessarily correspond to the size calculated by adding the storage requirements of the individual members. The /Zp compiler option and the pack pragma affect alignment boundaries for members."
Speaking of Watch window, I think it is simply shows you the size of the pointer (const char*) itself. Try to recompile program in 64-bit mode and check what Watch window would show then. If I am right, then you will see 8.
The reason that Things Go Wrong™ here is that you have chosen a too low level of abstraction, the memcmp.
One level up you have strcmp and wcscmp.
And one level up from that you have std::string and std::wstring.
The "speed" (hah!) of your chosen lowest level possible abstraction is offset by
Incorrect result.
Inefficiency due to lack of type knowledge (wide or narrow string, your code doesn't know).
Inefficiency due to lack of data knowledge (uppercase or lowercase).
Instead of wasting time on fixing the problems of the inefficient lowest level code, and wasting time on figuring out baffling details of low level tools, use a higher and safer level of abstraction.
Just for the record, sizeof( "abcd" ) is 5. The watch window is probably, as Hans Passant remarked, displaying the size of a pointer. However, I disagree with Hans that the debugger generally has no way to know the size of an array: for a debug build it can know anything and everything about the original source, including the verbatim original source if needed (and it is displaying that verbatim original source, in context). So, that 4 is IMHO a bug one way or the other. Either a bug in the debugger code, or a bug in its design.
Sizeof is a operator that evaluates to a size_t,usually an unsigned int on 32 bit platforms. That is why you see it as 4 in the debugger. The sizeof operator is also an rvalue, so you cannot set a watch point on the memory. If you could, the location would contain 5. The size of your string plus terminator.

How do I safely format floats/doubles with C's sprintf()?

I'm porting one of my C++ libraries to a somewhat wonky compiler -- it doesn't support stringstreams, or C99 features like snprintf(). I need to format int, float, etc values as char*, and the only options available seem to be 1) use sprintf() 2) hand-roll formatting procedures.
Given this, how do I determine (at either compile- or run-time) how many bytes are required for a formatted floating-point value? My library might be used for fuzz-testing, so it needs to handle even unusual or extreme values.
Alternatively, is there a small (100-200 lines preferred), portable implementation of snprintf() available that I could simply bundle with my library?
Ideally, I would end up with either normal snprintf()-based code, or something like this:
static const size_t FLOAT_BUFFER_SIZE = /* calculate max buffer somehow */;
char *fmt_double(double x)
{
char *buf = new char[FLOAT_BUFFER_SIZE + 1];
sprintf(buf, "%f", x);
return buf;
}
Related questions:
Maximum sprintf() buffer size for integers
Maximum sprintf() buffer size for %g-formatted floats
Does the compiler support any of ecvt, fcvt or gcvt? They are a bit freakish, and hard to use, but they have their own buffer (ecvt, fcvt) and/or you may get lucky and find the system headers have, as in VC++, a definition of the maximum number of chars gcvt will produce. And you can take it from there.
Failing that, I'd consider the following quite acceptable, along the lines of the code provided. 500 chars is pretty conservative for a double; valid values are roughly 10^-308 to 10^308, so even if the implementation is determined to be annoying by printing out all the digits there should be no overflow.
char *fmt_double(double d) {
static char buf[500];
sprintf(buf,"%f",d);
assert(buf[sizeof buf-1]==0);//if this fails, increase buffer size!
return strdup(buf);
}
This doesn't exactly provide any amazing guarantees, but it should be pretty safe(tm). I think that's as good as it gets with this sort of approach, unfortunately. But if you're in the habit of regularly running debug builds, you should at least get early warning of any problems...
I think GNU Libiberty is what you want. You can just include the implementation of snprintf.
vasprintf.c - 152 LOC.