#include #include #include /* * VLA_ALLOC_LIMIT - 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 causes too much per-allocation * overhead */ #define VLA_ALLOC_LIMIT (4096*8) #if (__STDC_VERSION__ - 0 >= 199901L) /* C99 */ && \ (__STDC_NO_VLA__ - 0 < 1L) /* C11 feature test for VLA support */ /* * VLA_ALLOC_ALLOCATE - allocate a chunk of memory from stack * if the size is smaller than |VLA_ALLOC_LIMIT| (and use * |malloc()| otherwise) and store the pointer to that memory * into |dest| * * Notes: * - We still use |1| as size for the VLA array if we use the * |malloc()| codepath because the ISO C1X standard is a bit * unclear in this corner case and (Sun Studio) lint(1) complains * about zero-sized VLA arrays * - We do not provide a codepath for |alloca()| as fallback * because there are platforms which define |alloca()| via a * wrapper around |malloc()| and therefore do not provide any * performance benefits */ #define VLA_ALLOC_ALLOCATE(dest, name, size) \ const size_t mem_mallocsize##name = (size); \ void *mem_malloc##name; \ char *mem_vla##name[mem_mallocsize##name > VLA_ALLOC_LIMIT?1:(mem_mallocsize##name)]; \ (((mem_mallocsize##name) > VLA_ALLOC_LIMIT)? \ ((dest) = mem_malloc##name = malloc(mem_mallocsize##name)): \ (mem_malloc##name = NULL, (dest) = mem_vla##name)) #else #define VLA_ALLOC_ALLOCATE(dest, name, size) \ void *mem_malloc##name; \ ((dest) = mem_malloc##name = malloc(size)) #endif /* * Free memory allocated via |VLA_ALLOC_ALLOCATE()| * POSIX |free()| handles NULL-pointers automagically */ #define VLA_ALLOC_FREE(name) free(mem_malloc##name) int main(int ac, char *av[]) { void *frog_mem, *fish_mem; size_t i; for (i=0 ; i < ((VLA_ALLOC_LIMIT*5L)/4L) ; i++) { VLA_ALLOC_ALLOCATE(frog_mem, frog, i); if (frog_mem) { (void)strncpy(frog_mem, "use memory to store frog data", i); } VLA_ALLOC_ALLOCATE(fish_mem, fish, i*2); if (frog_mem) { (void)strncpy(fish_mem, "use memory to store fish data", i*2); } VLA_ALLOC_FREE(frog); VLA_ALLOC_FREE(fish); } return (EXIT_SUCCESS); }