summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosé Fonseca <[email protected]>2008-04-10 22:57:21 +0900
committerJosé Fonseca <[email protected]>2008-04-11 09:32:26 +0900
commitbc56e87ce180ddca63bcb9774366fc380214a2ef (patch)
treee7286d06f425e1683875414fe106723780957fa3
parentc95dcc49629b72b95826e87e067d7a48753605fb (diff)
gallium: Attribute realloc leaks to the first malloc call.
-rw-r--r--src/gallium/auxiliary/util/p_debug_mem.c71
-rw-r--r--src/gallium/auxiliary/util/u_double_list.h8
2 files changed, 68 insertions, 11 deletions
diff --git a/src/gallium/auxiliary/util/p_debug_mem.c b/src/gallium/auxiliary/util/p_debug_mem.c
index 97ec9c5b392..aba69c02946 100644
--- a/src/gallium/auxiliary/util/p_debug_mem.c
+++ b/src/gallium/auxiliary/util/p_debug_mem.c
@@ -73,6 +73,25 @@ static struct list_head list = { &list, &list };
static unsigned long last_no = 0;
+static INLINE struct debug_memory_header *
+header_from_data(void *data)
+{
+ if(data)
+ return (struct debug_memory_header *)((char *)data - sizeof(struct debug_memory_header));
+ else
+ return NULL;
+}
+
+static INLINE void *
+data_from_header(struct debug_memory_header *hdr)
+{
+ if(hdr)
+ return (void *)((char *)hdr + sizeof(struct debug_memory_header));
+ else
+ return NULL;
+}
+
+
void *
debug_malloc(const char *file, unsigned line, const char *function,
size_t size)
@@ -92,7 +111,7 @@ debug_malloc(const char *file, unsigned line, const char *function,
LIST_ADDTAIL(&hdr->head, &list);
- return (void *)((char *)hdr + sizeof(*hdr));
+ return data_from_header(hdr);
}
void
@@ -104,7 +123,7 @@ debug_free(const char *file, unsigned line, const char *function,
if(!ptr)
return;
- hdr = (struct debug_memory_header *)((char *)ptr - sizeof(*hdr));
+ hdr = header_from_data(ptr);
if(hdr->magic != DEBUG_MEMORY_MAGIC) {
debug_printf("%s:%u:%s: freeing bad or corrupted memory %p\n",
file, line, function,
@@ -133,16 +152,46 @@ void *
debug_realloc(const char *file, unsigned line, const char *function,
void *old_ptr, size_t old_size, size_t new_size )
{
- void *new_ptr = NULL;
-
- if (new_size != 0) {
- new_ptr = debug_malloc( file, line, function, new_size );
-
- if( new_ptr && old_ptr )
- memcpy( new_ptr, old_ptr, old_size );
+ struct debug_memory_header *old_hdr, *new_hdr;
+ void *new_ptr;
+
+ if(!old_ptr)
+ return debug_malloc( file, line, function, new_size );
+
+ if(!new_size) {
+ debug_free( file, line, function, old_ptr );
+ return NULL;
}
+
+ old_hdr = header_from_data(old_ptr);
+ if(old_hdr->magic != DEBUG_MEMORY_MAGIC) {
+ debug_printf("%s:%u:%s: reallocating bad or corrupted memory %p\n",
+ file, line, function,
+ old_ptr);
+ debug_assert(0);
+ return NULL;
+ }
+
+ /* alloc new */
+ new_hdr = real_malloc(sizeof(*new_hdr) + new_size);
+ if(!new_hdr)
+ return NULL;
+ new_hdr->no = old_hdr->no;
+ new_hdr->file = old_hdr->file;
+ new_hdr->line = old_hdr->line;
+ new_hdr->function = old_hdr->function;
+ new_hdr->size = new_size;
+ new_hdr->magic = DEBUG_MEMORY_MAGIC;
+ LIST_REPLACE(&old_hdr->head, &new_hdr->head);
+
+ /* copy data */
+ new_ptr = data_from_header(new_hdr);
+ memcpy( new_ptr, old_ptr, old_size < new_size ? old_size : new_size );
+
+ /* free old */
+ old_hdr->magic = 0;
+ real_free(old_hdr);
- debug_free( file, line, function, old_ptr );
return new_ptr;
}
@@ -162,7 +211,7 @@ debug_memory_end(unsigned long start_no)
struct debug_memory_header *hdr;
void *ptr;
hdr = LIST_ENTRY(struct debug_memory_header, entry, head);
- ptr = (void *)((char *)hdr + sizeof(*hdr));
+ ptr = data_from_header(hdr);
if(start_no <= hdr->no && hdr->no < last_no ||
last_no < start_no && (hdr->no < last_no || start_no <= hdr->no))
debug_printf("%s:%u:%s: %u bytes at %p not freed\n",
diff --git a/src/gallium/auxiliary/util/u_double_list.h b/src/gallium/auxiliary/util/u_double_list.h
index 8cb10c98206..d108d92e52b 100644
--- a/src/gallium/auxiliary/util/u_double_list.h
+++ b/src/gallium/auxiliary/util/u_double_list.h
@@ -70,6 +70,14 @@ struct list_head
(__list)->prev = (__item); \
} while(0)
+#define LIST_REPLACE(__from, __to) \
+ do { \
+ (__to)->prev = (__from)->prev; \
+ (__to)->next = (__from)->next; \
+ (__from)->next->prev = (__to); \
+ (__from)->prev->next = (__to); \
+ } while (0)
+
#define LIST_DEL(__item) \
do { \
(__item)->prev->next = (__item)->next; \