C99 Features

Roland Mainz rmainz at redhat.com
Tue Jul 7 12:33:01 EDT 2015

----- Original Message -----
> From: "Nathaniel McCallum" <npmccallum at redhat.com>
> To: krbdev at mit.edu
> Sent: Tuesday, June 16, 2015 3:06:39 AM
> Subject: C99 Features
> It has been 16 years. GCC has had support for many C99 features for a
> LongTimeNowTM. Clang has had them since the beginning. Clang also now
> has official Windows builds (as well as many other platforms).
> Of course, MSVC still lags behind. However, they have started
> implementing features, including the following since MSVC 2013 [1]:
>  * _Bool
>  * Compound literals
>  * Designated initializers
>  * Mixing declarations with code
> MS has also implemented most of the C99 libraries[2] and has already
> announced complete support for the C99 standard library in MSVC
> 2015[3]. One of the big elephants in the room is VLAs. MS is unlikely
> to ever support them. But, it is also MS's stated policy to only
> incorporate C features that are required for C++[4]. I'm not sure that
> MIT should hold back support for new C features because MS only wants
> to ship a C++ compiler.
> So how about it? Can MIT start using C99 features? Even a subset of the
> features would be helpful. I particularly care about all the above C99
> features that MS implemented plus VLAs. The latter, in particular, can
> eliminate a lot of heap allocations.

1. Using |bool| would be a very good idea because it allows a lot of optimizations with low optimizer settings. There is a possible risk of namespace clash with |krb5_boolean| so I suggest to use a new define like |krb5_std_bool| if we want it in public APIs (which we should do (question for myself... did the ISO C spec define a size for |bool| ?))
2. IMHO we should use |restrict| where possible (e.g. crypto, string-heavy code etc.) to squeeze out some performance
3. VLAs can be tricky, but usually aren't a big problem if used with care (I've been there with Solaris's OS/Net long ago and it was a *pain* politically-wise and getting all tools fixed, but these should be issues if the past). Main issue is to define an upper per-allocation limit which can be allocated via VLAs and then switch to |malloc()| if the allocation is larger than that limit (typically |getpagesize()*8| was considered a "safe" limit in Solaris OS/Net). If I recall it correctly the following code should handle the issues correctly (except that it should use the ISO C99 feature test macros to test whether VLAs are available (this will cover the "limitations" of the Microsoft compiler)):
-- snip --
#include <stdlib.h>
#include <stdio.h>

 * Define upper limit for VLA allocations
 * This should be derived from |getpagesize()| but we
 * can't do it directly here because |getpagesize()| is
 * a syscall and therefore too much overhead
#define VLA_ALLOC_LIMIT (4096*8)

 * Allocate a chunk of memory from stack if the size is smaller
 * than |VLA_ALLOC_LIMIT| and use |malloc()| otherwise
#define VLA_ALLOC_ALLOCATE(dest, name, size) \
	char *mem_malloc##name, mem_vla##name[(size) > VLA_ALLOC_LIMIT?1:(size)]; \
	(((size) > VLA_ALLOC_LIMIT)? \
		(dest = mem_malloc##name = malloc(size)): \
		(mem_malloc##name = NULL, dest = mem_vla##name))
 * Free memory allocated via |VLA_ALLOC_ALLOCATE()|
 * free(3p) handles NULL-pointers automagically
#define VLA_ALLOC_FREE(name) free(mem_malloc##name);

int main(int ac, char *av[])
	void *x;
	size_t i;
	for (i=0 ; i < (VLA_ALLOC_LIMIT*27) ; i+=17)
		VLA_ALLOC_ALLOCATE(x, foo, i);

		/* use variable |x| after checking for
		 * allocation failure (|x == NULL|) */


-- snip --



  __ .  . __
 (o.\ \/ /.o) rmainz at redhat.com
  \__\/\/__/  IPA/Kerberos5 team
  /O /==\ O\  
 (;O/ \/ \O;)

More information about the krbdev mailing list