C11: A New C Standard Aiming at Safer Programming
blog.smartbear.com
blog.smartbear.com
//C11, safe version of strcat
errno_t strcat_s(char * restrict s1,
rsize_t s1max,
const char * restrict s2);
strcat_s() copies no more than s1max bytes to s1. The second function, strcpy_s() requires that s1max isn't bigger than the size of s2 in order to prevent an out-of-bounds read: //C11, safe version of strcpy
errno_t strcpy_s(char * restrict s1,
rsize_t s1max,
const char * restrict s2);
Originally, all of the bounds-checking libraries were developed by Microsoft's Visual C++ team. The C11 implementation is similar but not identical.There are so many problems with this. Yet another slightly different string manipulation function? Why not standardize on one of the already existing ones, such as strlcat/strlcpy? I can see people making some big mistakes with strcat_s, since the size passed is the number of unused characters left in s1, not the size of s1. And strcpy_s can cause a segfault if given an s1max that is greater than the size of s2. Why not only copy up to the first null character?
Also, these functions have the same name as the VC++ functions, but behave differently. In VC++, strcat_s takes the size of s1, not the space remaining. People are going to google for strcat_s, read the MSDN docs, and unknowingly add buffer overflows to their code.
Finally, these functions have annoying behavior. If they hit the limits passed to them, they erase s1. No best-effort. No copy whatever fits. Just destroy the data in the destination string.
strlcat/strlcpy solve all of the problems I've mentioned. See http://www.courtesan.com/todd/papers/strlcpy.html for more info about them. It's sad to see them only supported by *BSD and OS X.
There are valid reasons not to use strlcpy, but we need something like it. What we do not need is this _s shit, which has all the same problems (which sometimes matter, and sometimes don't) WHILE BEING MASSIVELY HARDER TO USE. And what's the advantage? Just that it returns an errno. That's fine, but what about the rest of it? Just read the instructions for it - it's crap! (I can imagine why they think they want it to work this way, because it gives you a fighting chance again non-0-terminated source strings, but it's just never going to work properly if you've only got one size argument.)
Using strlcpy, by contrast, is simplicity itself.
About 99% of the time when you're using strlcpy (and strlcat), you can just do your calls, passing the same size value into each one (how convenient), then check the length of the result using strlen. Is it one less than the size of the buffer? Yes? Then assume there's an overflow, and disregard the result, assuming you even care about that. This is very straightforward to do, and (unlike this _s junk) doesn't require you to go updating counts or checking maximum values or any of that error-prone nonsense. Just one check at the end, rather than a bunch of updates and stuff scattered all through your string code.
strlcpy! Just say yes!
I agree that the _s functions API are crap and quite bizarre, notice I did not say they weren't, but that doesn't mean another flawed solution should have been chosen instead.
strlcpy's behavior is the same as snprintf: return what the length would have been if there was enough room. That way one can recover from the error and realloc enough space. C programmers are used to this pattern.
At least now we have an ironclad reason not to ever use this garbage.
[edit: I almost wonder if someone on the committee deliberately put this in to sabotage the whole "safe C string functions" farce. Reminds me of a Simpsons episode:
Speaker: Then it is unanimous, we are going to approve the bill to evacuate the town of Springfield in the great state of—
Congressman: Wait a second, I want to tack on a rider to that bill – $30 million of taxpayer money to support the perverted arts.
Speaker: All in favor of the amended Springfield-slash-pervert bill? [entire Congress boos] Bill defeated. [gavel]
You can even use Clang on Windows if you need (MinGW, Cygwin or compiled with Visual Studio). I'm not sure if you can integrate Clang in VS for example, or if it is possible to access the OS C libraries from Clang.
As a professional C programmer, I really couldn't care less whether or not Microsoft decides to implement C11 or remain in the dark ages. That ship sailed years ago.
But there is a ton of software being written right now that doesn't target Windows, with no plans to target Windows. The only way Windows users will ever be able to use that software is if Microsoft makes it easy enough to port.
The nail in the coffin will be when most of the games on Steam do not work in Windows. With most business software becoming web-based, the only holdouts left will be old businesses locked into their enterprise crapware.
https://github.com/rbultje/c99-to-c89
(see http://blogs.gnome.org/rbultje/2012/09/27/microsoft-visual-s...)
Can you give us a practical example of some code where variable-length arrays prove really useful?
1. Multidimensional arrays where the sizes are quasi-fixed but not known at compile time. Comes up in various kinds of grid-simulation code, for example. You could malloc() in this case, but then you lose the notational convenience of 2d arrays.
2. Refactoring code that uses #define'd constants, to take runtime instead of compile-time parameters. For example, a common first-pass to said grid-simulation code is to have some WIDTH and HEIGHT magic numbers, which you might later regret and want to make into command-line parameters. Refactoring is trivial if you have VLAs.
It also seems cleaner (to me) semantically. I can see why, implementation-wise, classic C auto arrays required constant sizes. But from a slightly higher-level perspective, whether a variable is auto or not, and whether its size is a compile-time constant or not, feel like independent decisions. It feels particularly messy that you have different notation for arrays whose sizes are known at compile time; the syntactic sugar there has some rough edges. I also find it cleaner if explicit malloc()s are used only when something beyond boilerplate is going on, letting the compiler handle the boilerplate case of allocating/deallocating a conceptually block-scoped array of size N.
void func(int M, int N, int P, double *a_flat) {
double (*a)[N][P] = (double (*)[N][P])a_flat;
// use a[i+1][j+2][k-1] instead of a_flat[((i+1)*N+(j+2))*P+k-1].There are also some possible applications here: http://gustedt.wordpress.com/2011/01/13/vla-as-function-argu...
In fairness, I've used them only rarely, but those few times I've used them have saved me a bit of grief.
I could easily live without them if required...
But if you write C11 that uses VLAs, it seems like it's still standard C11, sort of: VLAs aren't merely a vendor-specific extension, like the GCC extensions are, but an optional C11 feature which hasn't been deprecated. Nonetheless, a conforming C11 compiler doesn't have to accept your code, so in that sense your code isn't really "standard C11". Will there be more fine-grained names for the different subsets of the standard features, so you can say that such code is compliant with "maxi-C11" but not with "core C11" or something?
If you're absolutely sure that you can handle the power, you can always call alloca and get some stack-allocated space, even with ancient C compilers. Just make sure to enforce a reasonable upper limit. Also, never mix C99-style arrays and alloca.
It's a minor fix, but it's vastly better than what was there previously, and it's exactly the sort of change that works really well in C; incremental fixes that are carefully thought out and easy for both implementors and users to adopt.
What higher level? POSIX? Personally, I believe things like atomicity and alignment do belong into the language specification.
Also keep in mind that the multithreading support as specified by C11 is closely aligned with C++11.
[1] http://www.hpl.hp.com/techreports/2004/HPL-2004-209.html [2] http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53769
Adding a wildly different compiler shouldn't be the end of the world but it would need some build sys work and a new compiler wrapper.
Samy was focusing on a few archs that help debug the code. I got him access to the GCC build farm, but the ARM boxes there were fairly weak when I remember. Access to good hardware might help him move it along.
There has not been much about C11.
C++ folks do seem to care a lot about which features of boost are going to be folded into the language spec and runtimes and what else has been dreamt up for their baby, and how they're going to be able to be more efficient, safer and gosh-darnit just all-round smarter in future.
C programmers mumble something about being busy and already having the tools they need to do everything, though (grudgingly) that VA_ARGS preprocessor extension from '99 was quite handy I suppose...
(I'm a C programmer by trade and history, working on C++ at the moment, just in case I pissed anyone off enough to start a holy war :)
C++ has always had the feeling of a language that isn't quite finished, so there's a lot of interest in where it's going next. C has the feeling of a language that does exactly what it sets out to do, so it's not really going anywhere.
However, the problem is that because MS doesn't adopt it, a lot of companies and projects still have coding standards that forbid the use of C99 constructs. This because of the (percieved) need to compile for Windows with MSVC some day. So MS not adopting C99 is a problem for adoption, even though most compilers support it fine.
"Originally, all of the bounds-checking libraries were developed by Microsoft's Visual C++ team. The C11 implementation is similar but not identical."
Picking a nit, but shouldn't this say "The C11 standard ..."? If C99 implementations are hard to find, I'd think it would be more so for C11.
Are there any C11 implementations? Or do you just pick the implementation and libraries that implements that largest set of C11 that are important to you?
If the guys from plan9 just get the Ken Thompson C compiler from plan9 and changed that C just a little bit, taking care that a plain C header could be added to that code the same way we could do with C++
only then, it would be possible to "just use Go" (plan9 C can be used with gcc using "fplan9-extensions")
The only thing it will be missing from plan9 c will be the automatic casting from the composition to the base struct.. but its just to cast to the base struct when you need to reference only the parent struct, polymorphism. (Ken Thompson called this effect as "Poor man classes")
Macros can be handy when you need to hide this nasty castings away when not using the plan9 extension..
the nice thing about "-std=c11 -fms-extensions" is that it works with gcc, clang and vc.