From 3fc56a0dc3390e5a5ac94bacb2110ba4dcf673ee Mon Sep 17 00:00:00 2001 From: "Sven M. Hallberg" <pesco@khjk.org> Date: Mon, 30 Nov 2015 16:37:00 +0100 Subject: [PATCH] add h_alloc() which calls errx() on failure and use it for all basic allocation Rationale: "Basic allocation" refers to things outside of parsing proper, mostly initialization. If such allocations fail, the system is globally emory-starved from which it will likely not recover by returning failure. In this case, terminating the process is in fact the most robust strategy as it may mean the difference between a permanent hang and a temporary crash. --- src/allocator.c | 15 ++++++++++----- src/allocator.h | 24 +++++++++++++----------- src/bitwriter.c | 6 ++---- src/internal.h | 2 +- src/pprint.c | 6 ++---- src/registry.c | 6 ++---- 6 files changed, 30 insertions(+), 29 deletions(-) diff --git a/src/allocator.c b/src/allocator.c index 4646dd8..cc259e6 100644 --- a/src/allocator.c +++ b/src/allocator.c @@ -47,15 +47,20 @@ struct HArena_ { jmp_buf *except; }; +void* h_alloc(HAllocator* mm__, size_t size) { + void *p = mm__->alloc(mm__, size); + if(!p) + h_platform_errx(1, "memory allocation failed (%uB requested)\n", (unsigned int)size); + return p; +} + HArena *h_new_arena(HAllocator* mm__, size_t block_size) { if (block_size == 0) block_size = 4096; struct HArena_ *ret = h_new(struct HArena_, 1); - struct arena_link *link = (struct arena_link*)mm__->alloc(mm__, sizeof(struct arena_link) + block_size); - if (!link) { - // TODO: error-reporting -- let user know that arena link couldn't be allocated - return NULL; - } + struct arena_link *link = (struct arena_link*)h_alloc(mm__, sizeof(struct arena_link) + block_size); + assert(ret != NULL); + assert(link != NULL); memset(link, 0, sizeof(struct arena_link) + block_size); link->free = block_size; link->used = 0; diff --git a/src/allocator.h b/src/allocator.h index d80209d..dc88af6 100644 --- a/src/allocator.h +++ b/src/allocator.h @@ -24,17 +24,6 @@ extern "C" { #endif -// TODO(thequux): Turn this into an "HAllocatorVtable", and add a wrapper that also takes an environment pointer. -typedef struct HAllocator_ { - void* (*alloc)(struct HAllocator_* allocator, size_t size); - void* (*realloc)(struct HAllocator_* allocator, void* ptr, size_t size); - void (*free)(struct HAllocator_* allocator, void* ptr); -} HAllocator; - -typedef struct HArena_ HArena ; // hidden implementation - -HArena *h_new_arena(HAllocator* allocator, size_t block_size); // pass 0 for default... - #if defined __llvm__ # if __has_attribute(malloc) # define ATTR_MALLOC(n) __attribute__((malloc)) @@ -49,6 +38,19 @@ HArena *h_new_arena(HAllocator* allocator, size_t block_size); // pass 0 for def # define ATTR_MALLOC(n) #endif +// TODO(thequux): Turn this into an "HAllocatorVtable", and add a wrapper that also takes an environment pointer. +typedef struct HAllocator_ { + void* (*alloc)(struct HAllocator_* allocator, size_t size); + void* (*realloc)(struct HAllocator_* allocator, void* ptr, size_t size); + void (*free)(struct HAllocator_* allocator, void* ptr); +} HAllocator; + +void* h_alloc(HAllocator* allocator, size_t size) ATTR_MALLOC(2); + +typedef struct HArena_ HArena ; // hidden implementation + +HArena *h_new_arena(HAllocator* allocator, size_t block_size); // pass 0 for default... + void* h_arena_malloc(HArena *arena, size_t count) ATTR_MALLOC(2); void h_arena_free(HArena *arena, void* ptr); // For future expansion, with alternate memory managers. void h_delete_arena(HArena *arena); diff --git a/src/bitwriter.c b/src/bitwriter.c index 74e2734..bcc21dd 100644 --- a/src/bitwriter.c +++ b/src/bitwriter.c @@ -12,10 +12,8 @@ HBitWriter *h_bit_writer_new(HAllocator* mm__) { HBitWriter *writer = h_new(HBitWriter, 1); memset(writer, 0, sizeof(*writer)); - writer->buf = mm__->alloc(mm__, writer->capacity = 8); - if (!writer) { - return NULL; - } + writer->buf = h_alloc(mm__, writer->capacity = 8); + assert(writer != NULL); memset(writer->buf, 0, writer->capacity); writer->mm__ = mm__; writer->flags = BYTE_BIG_ENDIAN | BIT_BIG_ENDIAN; diff --git a/src/internal.h b/src/internal.h index 776f636..10db4b2 100644 --- a/src/internal.h +++ b/src/internal.h @@ -49,7 +49,7 @@ rtype_t name##__m(HAllocator* mm__) // Functions with arguments are difficult to forward cleanly. Alas, we will need to forward them manually. -#define h_new(type, count) ((type*)(mm__->alloc(mm__, sizeof(type)*(count)))) +#define h_new(type, count) ((type*)(h_alloc(mm__, sizeof(type)*(count)))) #define h_free(addr) (mm__->free(mm__, (addr))) #ifndef __cplusplus diff --git a/src/pprint.c b/src/pprint.c index 11ec3d6..9c7c652 100644 --- a/src/pprint.c +++ b/src/pprint.c @@ -186,13 +186,11 @@ static void unamb_sub(const HParsedToken* tok, struct result_buf *buf) { char* h_write_result_unamb(const HParsedToken* tok) { struct result_buf buf = { - .output = (&system_allocator)->alloc(&system_allocator, 16), + .output = h_alloc(&system_allocator, 16), .len = 0, .capacity = 16 }; - if (!buf.output) { - return NULL; - } + assert(buf.output != NULL); unamb_sub(tok, &buf); append_buf_c(&buf, 0); return buf.output; diff --git a/src/registry.c b/src/registry.c index 2ebac1a..d905320 100644 --- a/src/registry.c +++ b/src/registry.c @@ -46,10 +46,8 @@ static int compare_entries(const void* v1, const void* v2) { } HTokenType h_allocate_token_type(const char* name) { - Entry* new_entry = (&system_allocator)->alloc(&system_allocator, sizeof(*new_entry)); - if (!new_entry) { - return TT_INVALID; - } + Entry* new_entry = h_alloc(&system_allocator, sizeof(*new_entry)); + assert(new_entry != NULL); new_entry->name = name; new_entry->value = 0; Entry* probe = *(Entry**)tsearch(new_entry, &tt_registry, compare_entries); -- GitLab