Adding strlcpy() to glibc
lwn.net
lwn.net
https://code.google.com/p/slibc/
At a glance, this seems like a better solution than any of alternatives: require the buffer length to always be specified, and call a user controlled handler instead of allowing an overflow. This handler defaults to abort().
While there are fine arguments to be made for using a real string library like bstring, are there downsides to the str_s approach compared to using the str, strp, or strl family of functions?
I personally don't think this is a big problem, as the kinds of issues that would cause the invalid parameter handler to be called usually are not recoverable no matter where they originate from.
But I can definitely see why the loss of control is technically troubling - those random libraries could be calling set_constraint_handler_s() and thus causing your code to keep running and not abort(), forcing you to rely on your second defense of checking the return values from all the functions.
(There's also a potential political issue with str..._s(), but I won't go into that one.)
Also, if you dig into the Annex K API there are quite a few problems with it, both technical and practical. It was half-baked. Some parts are salvageable, but really the API as a whole should be trashed.
strlcpy is useful and prevalent. Let's not let perfect be the enemy of good.
Trying to solve string management problems in C by getting everybody to agree on a "safe", comprehensive API is misguided and a waste of time.
But if you know how long is the source and destiny buffers (and if you are using str[nl]cpy, probably you know it), you could use memcpy and get a much more faster copy.
char buffer[1 << 24}]
strncpy(buffer, "a", sizeof(buffer));
will set all of the array to zero, instead of just copying two bytes.And as you noted, it won't NUL terminate the string. Since strncpy() doesn't return C strings, it's not really a "C string" function. It's a horrible, inefficient bastardization which should be used by no one.
size_t len = (src_size < dst_size) ? src_size : dst_size;
memcpy (dst, src, len); // or memmove
dst[len-1] = 0;
So not fills unecesary 0's and it's much more faster that any str?cpy1) char buf[1024]; strncpy(buf, "hello", sizeof buf);
now fills in 5 characters, and 1019 0 bytes in the buffer. (i.e. you're writing 1018 nul bytes that's usually not needed)
2) char buf[5]; strncpy(buf, "hello", sizeof buf);
results in buf NOT being a string. (it isn't nul terminated). So with most use of strncpy, you'll have to also do
buf[sizeof buf - 1] = 0;PHP's Zend Engine has safely-handled strings, for example, but we do that by reference-counting them and having an explicit length.
https://github.com/git/git/blob/master/strbuf.c
https://www.kernel.org/pub/software/scm/git/docs/technical/a...
Somehow, the message seems to keep getting lost.
Visual C++ is a C++ compiler, that is the language that is relevant to keep supporting for systems programming in Windows. Time to move forward.
As of Windows 8 it is now possible to use C++ in DDK and kernel team is making the code compile C++ compatible.
C89 support is good enough for backwards compatibility and what has been added from C99 was what is required from the C++11 standard.
C was already feeling primitive in 1993 when compared with languages like Turbo Pascal and C++ offered so much more in terms of type safety and modular programming.
So yes, it has been forward from C since a few decades already.
In fact, compound literal syntax is probably incompatible with C++, because similar syntax in C++ requires entirely different object lifetimes--expression scope in C++, block scope in C99.
Actually, I think the target may be C11, as I doubt they'll add VLAs.
(I'm willing to skip C99 for C11 because am sick of dancing around Visual Studio for compatibility. Clang for Visual Studio is looking really appealing to me.)
Why they have the only world's C++ compiler that can't handle C baffles me. What did they screw up so badly in their implementation that every other C/C++ compiler got right?
Why? C++ was born at AT&T, the same place C was born.
Given its design to be as compatible with C as possible, it was quite natural for C compiler vendors to bundle a C++ compiler with their C compiler.
There isn't any requirement in ANSI/ISO C++ that a C++ compiler vendor is obliged to support C.
Microsoft's decision is not technical, but political.
From their point of view, if you want to write C style code, there isn't nothing in C++ that prevents it.
On the other hand, C cannot provide at the language level the mechanisms available in C++ to write safe code.
Not to mention that Windows APIs are mostly COM based since the Windows XP, anyway.
If you want C on Windows, or to have fun using COM or WinRT from C, there are plenty of other compilers available.
Both Symbian and BeOS were C++ based OS. I for one, enjoy seeing Windows going into the same direction.
http://msdn.microsoft.com/en-us/library/hh409293.aspx
http://blogs.msdn.com/b/vcblog/archive/2013/07/19/c99-librar...
http://blogs.msdn.com/b/vcblog/archive/2014/06/03/visual-stu...
No they did not.
Herb Sutter was very explicit about this.
- C99 language features as required by the C++11/14 standards
- compound literal syntax just to allow certain well known open source project to be ported to Windows, mainly game related projects
Nothing else is planned as shown on his slides.
http://channel9.msdn.com/Events/Visual-Studio/Launch-2013/VS...
Edit: Added link to Visual Studio 2013 launch presentation from Herb Sutter.
Visual Studio 2013 supports both compound literals and designated initializers. That required core language changes, and are arguably the two biggest language changes in C99 from a syntax standpoint. Both were rejected by C++ and will never appear in C++, so they're entirely unnecessary.
See http://msdn.microsoft.com/en-us/library/hh409293.aspx
See also http://blogs.msdn.com/b/vcblog/archive/2013/07/19/c99-librar...
And Visual Studio 2014 added most of the missing pieces, including a standards compliant snprintf. See http://blogs.msdn.com/b/vcblog/archive/2014/06/03/visual-stu...
Heck, they even met C99 half-way on the restrict qualifier by adding a __restrict keyword. C++ also rejected restrict, FWIW.
Those are all comprehensive, non-trivial changes, and most are irrelevant to C++. Microsoft can talk it down however they want, but the new features speak for themselves.
I don't even use Visual Studio. Or Windows for that matter. But I value standards compliance and portability, and I was happy to see Microsoft change their mind on this. They did it rather quietly ("No, we aren't targeting C anymore, but here are almost all the new C features which we said we'd never support in a million years."), perhaps because they so adamantly refused to support it before.
Yes, the reason they finally capitulated is because there was simply too much open source C99 software in the wild, and it was becoming a pain point for Windows developers not being able to use that software with their preferred development environment--Visual Studio. But at this point they've implemented almost all the features that actually matter.
Features like VLAs and _Complex are rarely used, so I doubt Visual Studio will get that. But both are optional in C11 anyhow. With little effort--one of the biggest changes being _Generic--Visual Studio could become C11 compliant, at least in practice.
Still, I was a supporter of their decision, given the added safety and expressiveness that C++ has over C.
System programming languages only get replaced when an OS vendor decides to push them aside from their SDKs.
But as someone pointed out to me, things seem to have changed a bit more than I thought.
gcc's C++ compiler doesn't handle C past C89 either; you can't use C99 features when compiling with g++. There is a separate C compiler that's part of the GNU Compiler Collection, but then there's also a Fortran and a Go compiler: gcc includes a lot of languages. MSVC++ doesn't; it's just a C++ compiler, not a Fortran or Java or C compiler. Linux norms are a bit more polyglot, so gcc is more polyglot than MSVC++ is.
I personally like C, so it'd be nice if Microsoft shipped a C compiler in addition to a C++ compiler, but they've chosen not to. As a result, the "C" you can write is precisely the C that is also valid C++, and you can't use any features that aren't valid C++. If you really want there to be a language "C/C++" again that all C++ compilers can be expected to handle, you'd have to convince the C++ standards committee to add C99 or C11 features to the next C++1x.
(When I first discovered strlcpy/strlcat I went and changed a bunch of string-fiddling code to use them and it was really amazing how much simpler everything became. Virtually all of my bounds checks could go away, leaving just the string stuff. Much nicer? Well, I wouldn't go that far. But certainly fewer ways for it to go wrong.)
So how hard would it be to add a return value indicating this?
What most people want is some simple functions that that can tell you if something would have gone bad. (e.g. truncate the copied string and tell you if it was truncated)