diff options
author | Evan Huus <eapache@gmail.com> | 2013-01-23 01:11:36 +0000 |
---|---|---|
committer | Evan Huus <eapache@gmail.com> | 2013-01-23 01:11:36 +0000 |
commit | 681a3ad5a2d80a1b76e336256fb90f9caf2b89df (patch) | |
tree | e0c520578e02285bfd71100c4df8f4dbc0625ad9 /epan/wmem | |
parent | c25c5915c5c94b5c70e51e4ca43f1aa5286c6349 (diff) |
Handle NULL-pointers and 0-lengths in a much simpler allocator-agnostic way,
and document the fact that allocator authors don't have to care.
svn path=/trunk/; revision=47220
Diffstat (limited to 'epan/wmem')
-rw-r--r-- | epan/wmem/wmem_allocator_simple.c | 36 | ||||
-rw-r--r-- | epan/wmem/wmem_core.c | 33 |
2 files changed, 37 insertions, 32 deletions
diff --git a/epan/wmem/wmem_allocator_simple.c b/epan/wmem/wmem_allocator_simple.c index 9269845e56..da28353180 100644 --- a/epan/wmem/wmem_allocator_simple.c +++ b/epan/wmem/wmem_allocator_simple.c @@ -50,11 +50,7 @@ wmem_simple_alloc(void *private_data, const size_t size) buf = g_malloc(size); - /* alloc is allowed to return NULL if the requested size is 0, in - * which case we don't need to add it to the hash table */ - if (buf) { - g_hash_table_insert(allocator->block_table, buf, buf); - } + g_hash_table_insert(allocator->block_table, buf, buf); return buf; } @@ -70,21 +66,12 @@ wmem_simple_realloc(void *private_data, void *ptr, const size_t size) newptr = g_realloc(ptr, size); if (ptr != newptr) { - /* realloc actually moved the memory block. */ - if (ptr) { - /* ptr is allowed to be NULL in which case it is assumed to have 0 - * length. If it is non-NULL we need to remove it from the hash - * table, as realloc reclaimed it during the move, however calling - * g_hash_table_remove() would trigger a double-free (because we - * registered g_free() as the destructor function for the hash - * table) so we use g_hash_table_steal() instead. */ - g_hash_table_steal(allocator->block_table, ptr); - } - if (newptr) { - /* realloc is allowed to return NULL if the requested size is 0, in - * which case we don't need to add it to the hash table */ - g_hash_table_insert(allocator->block_table, newptr, newptr); - } + /* Realloc actually moved the memory block, so we need to replace the + * value in our hash table. Calling g_hash_table_remove() would trigger + * a g_free() which is incorrect since realloc already reclaimed the old + * block, so use g_hash_table_steal() instead. */ + g_hash_table_steal(allocator->block_table, ptr); + g_hash_table_insert(allocator->block_table, newptr, newptr); } return newptr; @@ -97,12 +84,9 @@ wmem_simple_free(void *private_data, void *ptr) allocator = (wmem_simple_allocator_t*) private_data; - /* free is a no-op on a NULL pointer */ - if (ptr) { - /* remove() takes care of calling g_free() for us since we set up the - * hash table with g_hash_table_new_full() */ - g_hash_table_remove(allocator->block_table, ptr); - } + /* remove() takes care of calling g_free() for us since we set up the + * hash table with g_hash_table_new_full() */ + g_hash_table_remove(allocator->block_table, ptr); } static void diff --git a/epan/wmem/wmem_core.c b/epan/wmem/wmem_core.c index 0cb8c64aed..e15f1ff913 100644 --- a/epan/wmem/wmem_core.c +++ b/epan/wmem/wmem_core.c @@ -37,6 +37,10 @@ void * wmem_alloc(wmem_allocator_t *allocator, const size_t size) { + if (size == 0) { + return NULL; + } + return allocator->alloc(allocator->private_data, size); } @@ -44,24 +48,41 @@ void * wmem_alloc0(wmem_allocator_t *allocator, const size_t size) { void *buf; + + if (size == 0) { + return NULL; + } buf = wmem_alloc(allocator, size); return memset(buf, 0, size); } -void * -wmem_realloc(wmem_allocator_t *allocator, void *ptr, const size_t size) -{ - return allocator->realloc(allocator->private_data, ptr, size); -} - void wmem_free(wmem_allocator_t *allocator, void *ptr) { + if (ptr == NULL) { + return; + } + allocator->free(allocator->private_data, ptr); } +void * +wmem_realloc(wmem_allocator_t *allocator, void *ptr, const size_t size) +{ + if (ptr == NULL) { + return wmem_alloc(allocator, size); + } + + if (size == 0) { + wmem_free(allocator, ptr); + return NULL; + } + + return allocator->realloc(allocator->private_data, ptr, size); +} + void wmem_free_all(wmem_allocator_t *allocator) { |