summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/README.wmem6
-rw-r--r--epan/wmem/wmem_allocator_simple.c36
-rw-r--r--epan/wmem/wmem_core.c33
3 files changed, 43 insertions, 32 deletions
diff --git a/doc/README.wmem b/doc/README.wmem
index 7740d7f37a..3b09935a0a 100644
--- a/doc/README.wmem
+++ b/doc/README.wmem
@@ -259,6 +259,12 @@ code in most cases - they are primarily optimisations for use by data
structures that wmem might want to implement (it's hard, for example, to
implement a dynamically sized array without some form of realloc).
+Also note that allocators do not have to handle NULL pointers or 0-length
+requests in any way - those checks are done in an allocator-agnostic way
+higher up in wmem. Allocator authors can assume that all incoming pointers
+(to realloc and free) are non-NULL, and that all incoming lengths (to malloc
+and realloc) are non-0.
+
4.1.3 Producer/Manager Functions
- free_all()
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)
{