Avoid variable length arrays and remove declarations within code

MSVC doesn't support C99, and building as C++ to be able to use them is
dangerous, as C++ and C99 are incompatible.

Introduce a VARIABLE_ARRAY macro that either uses VLA when supported,
or alloca() otherwise. Note that using alloca() inside loops doesn't
quite work like VLAs, thus the use of VARIABLE_ARRAY there is discouraged.
It might be worth investigating ways to check whether VARIABLE_ARRAY is
used in such context at runtime in debug builds and bail out if that
happens.
This commit is contained in:
Mike Hommey 2012-04-24 23:22:02 +02:00 committed by Jason Evans
parent f278994029
commit 8b49971d0c
7 changed files with 43 additions and 18 deletions

View File

@ -319,6 +319,20 @@ static const bool config_ivsalloc =
#define ALIGNMENT_CEILING(s, alignment) \ #define ALIGNMENT_CEILING(s, alignment) \
(((s) + (alignment - 1)) & (-(alignment))) (((s) + (alignment - 1)) & (-(alignment)))
/* Declare a variable length array */
#if __STDC_VERSION__ < 199901L
# ifdef _MSC_VER
# include <malloc.h>
# define alloca _alloca
# else
# include <alloca.h>
# endif
# define VARIABLE_ARRAY(type, name, count) \
type *name = alloca(sizeof(type) * count)
#else
# define VARIABLE_ARRAY(type, name, count) type name[count]
#endif
#ifdef JEMALLOC_VALGRIND #ifdef JEMALLOC_VALGRIND
/* /*
* The JEMALLOC_VALGRIND_*() macros must be macros rather than functions * The JEMALLOC_VALGRIND_*() macros must be macros rather than functions

View File

@ -542,8 +542,9 @@ prof_free(const void *ptr, size_t size)
cassert(config_prof); cassert(config_prof);
if ((uintptr_t)ctx > (uintptr_t)1) { if ((uintptr_t)ctx > (uintptr_t)1) {
prof_thr_cnt_t *tcnt;
assert(size == isalloc(ptr, true)); assert(size == isalloc(ptr, true));
prof_thr_cnt_t *tcnt = prof_lookup(ctx->bt); tcnt = prof_lookup(ctx->bt);
if (tcnt != NULL) { if (tcnt != NULL) {
tcnt->epoch++; tcnt->epoch++;

View File

@ -640,14 +640,14 @@ arena_chunk_purge(arena_t *arena, arena_chunk_t *chunk)
if (mapelm->bits & CHUNK_MAP_LARGE) if (mapelm->bits & CHUNK_MAP_LARGE)
pageind += mapelm->bits >> LG_PAGE; pageind += mapelm->bits >> LG_PAGE;
else { else {
size_t binind;
arena_bin_info_t *bin_info;
arena_run_t *run = (arena_run_t *)((uintptr_t) arena_run_t *run = (arena_run_t *)((uintptr_t)
chunk + (uintptr_t)(pageind << LG_PAGE)); chunk + (uintptr_t)(pageind << LG_PAGE));
assert((mapelm->bits >> LG_PAGE) == 0); assert((mapelm->bits >> LG_PAGE) == 0);
size_t binind = arena_bin_index(arena, binind = arena_bin_index(arena, run->bin);
run->bin); bin_info = &arena_bin_info[binind];
arena_bin_info_t *bin_info =
&arena_bin_info[binind];
pageind += bin_info->run_size >> LG_PAGE; pageind += bin_info->run_size >> LG_PAGE;
} }
} }
@ -1056,11 +1056,12 @@ arena_bin_runs_first(arena_bin_t *bin)
if (mapelm != NULL) { if (mapelm != NULL) {
arena_chunk_t *chunk; arena_chunk_t *chunk;
size_t pageind; size_t pageind;
arena_run_t *run;
chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(mapelm); chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(mapelm);
pageind = ((((uintptr_t)mapelm - (uintptr_t)chunk->map) / pageind = ((((uintptr_t)mapelm - (uintptr_t)chunk->map) /
sizeof(arena_chunk_map_t))) + map_bias; sizeof(arena_chunk_map_t))) + map_bias;
arena_run_t *run = (arena_run_t *)((uintptr_t)chunk + run = (arena_run_t *)((uintptr_t)chunk +
(uintptr_t)((pageind - (mapelm->bits >> LG_PAGE)) << (uintptr_t)((pageind - (mapelm->bits >> LG_PAGE)) <<
LG_PAGE)); LG_PAGE));
return (run); return (run);
@ -1596,14 +1597,15 @@ arena_dalloc_bin(arena_t *arena, arena_chunk_t *chunk, void *ptr,
size_t pageind; size_t pageind;
arena_run_t *run; arena_run_t *run;
arena_bin_t *bin; arena_bin_t *bin;
size_t size; arena_bin_info_t *bin_info;
size_t size, binind;
pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE; pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;
run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind - run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind -
(mapelm->bits >> LG_PAGE)) << LG_PAGE)); (mapelm->bits >> LG_PAGE)) << LG_PAGE));
bin = run->bin; bin = run->bin;
size_t binind = arena_bin_index(arena, bin); binind = arena_bin_index(arena, bin);
arena_bin_info_t *bin_info = &arena_bin_info[binind]; bin_info = &arena_bin_info[binind];
if (config_fill || config_stats) if (config_fill || config_stats)
size = bin_info->reg_size; size = bin_info->reg_size;

View File

@ -520,7 +520,7 @@ static void
ctl_refresh(void) ctl_refresh(void)
{ {
unsigned i; unsigned i;
arena_t *tarenas[narenas]; VARIABLE_ARRAY(arena_t *, tarenas, narenas);
if (config_stats) { if (config_stats) {
malloc_mutex_lock(&chunks_mtx); malloc_mutex_lock(&chunks_mtx);
@ -1232,7 +1232,7 @@ arenas_purge_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
ret = EFAULT; ret = EFAULT;
goto label_return; goto label_return;
} else { } else {
arena_t *tarenas[narenas]; VARIABLE_ARRAY(arena_t *, tarenas, narenas);
malloc_mutex_lock(&arenas_lock); malloc_mutex_lock(&arenas_lock);
memcpy(tarenas, arenas, sizeof(arena_t *) * narenas); memcpy(tarenas, arenas, sizeof(arena_t *) * narenas);

View File

@ -498,7 +498,7 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque,
CTL_GET("arenas.narenas", &narenas, unsigned); CTL_GET("arenas.narenas", &narenas, unsigned);
{ {
bool initialized[narenas]; VARIABLE_ARRAY(bool, initialized, narenas);
size_t isz; size_t isz;
unsigned i, ninitialized; unsigned i, ninitialized;
@ -527,7 +527,7 @@ stats_print(void (*write_cb)(void *, const char *), void *cbopaque,
CTL_GET("arenas.narenas", &narenas, unsigned); CTL_GET("arenas.narenas", &narenas, unsigned);
{ {
bool initialized[narenas]; VARIABLE_ARRAY(bool, initialized, narenas);
size_t isz; size_t isz;
unsigned i; unsigned i;

View File

@ -36,7 +36,7 @@ JEMALLOC_ATTR(visibility("default"))
void void
_malloc_thread_cleanup(void) _malloc_thread_cleanup(void)
{ {
bool pending[ncleanups], again; bool pending[MALLOC_TSD_CLEANUPS_MAX], again;
unsigned i; unsigned i;
for (i = 0; i < ncleanups; i++) for (i = 0; i < ncleanups; i++)

View File

@ -30,11 +30,13 @@ test_bitmap_init(void)
bitmap_info_init(&binfo, i); bitmap_info_init(&binfo, i);
{ {
size_t j; size_t j;
bitmap_t bitmap[bitmap_info_ngroups(&binfo)]; bitmap_t *bitmap = malloc(sizeof(bitmap_t) *
bitmap_info_ngroups(&binfo));
bitmap_init(bitmap, &binfo); bitmap_init(bitmap, &binfo);
for (j = 0; j < i; j++) for (j = 0; j < i; j++)
assert(bitmap_get(bitmap, &binfo, j) == false); assert(bitmap_get(bitmap, &binfo, j) == false);
free(bitmap);
} }
} }
@ -50,12 +52,14 @@ test_bitmap_set(void)
bitmap_info_init(&binfo, i); bitmap_info_init(&binfo, i);
{ {
size_t j; size_t j;
bitmap_t bitmap[bitmap_info_ngroups(&binfo)]; bitmap_t *bitmap = malloc(sizeof(bitmap_t) *
bitmap_info_ngroups(&binfo));
bitmap_init(bitmap, &binfo); bitmap_init(bitmap, &binfo);
for (j = 0; j < i; j++) for (j = 0; j < i; j++)
bitmap_set(bitmap, &binfo, j); bitmap_set(bitmap, &binfo, j);
assert(bitmap_full(bitmap, &binfo)); assert(bitmap_full(bitmap, &binfo));
free(bitmap);
} }
} }
} }
@ -70,7 +74,8 @@ test_bitmap_unset(void)
bitmap_info_init(&binfo, i); bitmap_info_init(&binfo, i);
{ {
size_t j; size_t j;
bitmap_t bitmap[bitmap_info_ngroups(&binfo)]; bitmap_t *bitmap = malloc(sizeof(bitmap_t) *
bitmap_info_ngroups(&binfo));
bitmap_init(bitmap, &binfo); bitmap_init(bitmap, &binfo);
for (j = 0; j < i; j++) for (j = 0; j < i; j++)
@ -81,6 +86,7 @@ test_bitmap_unset(void)
for (j = 0; j < i; j++) for (j = 0; j < i; j++)
bitmap_set(bitmap, &binfo, j); bitmap_set(bitmap, &binfo, j);
assert(bitmap_full(bitmap, &binfo)); assert(bitmap_full(bitmap, &binfo));
free(bitmap);
} }
} }
} }
@ -95,7 +101,8 @@ test_bitmap_sfu(void)
bitmap_info_init(&binfo, i); bitmap_info_init(&binfo, i);
{ {
ssize_t j; ssize_t j;
bitmap_t bitmap[bitmap_info_ngroups(&binfo)]; bitmap_t *bitmap = malloc(sizeof(bitmap_t) *
bitmap_info_ngroups(&binfo));
bitmap_init(bitmap, &binfo); bitmap_init(bitmap, &binfo);
/* Iteratively set bits starting at the beginning. */ /* Iteratively set bits starting at the beginning. */
@ -125,6 +132,7 @@ test_bitmap_sfu(void)
} }
assert(bitmap_sfu(bitmap, &binfo) == i - 1); assert(bitmap_sfu(bitmap, &binfo) == i - 1);
assert(bitmap_full(bitmap, &binfo)); assert(bitmap_full(bitmap, &binfo));
free(bitmap);
} }
} }
} }