1 /* Copyright (c) 2017 The Expat Maintainers
2 * Copying is permitted under the MIT license. See the file COPYING
5 * memcheck.c : debug allocators for the Expat test suite
13 /* Structures to keep track of what has been allocated. Speed isn't a
14 * big issue for the tests this is required for, so we will use a
15 * doubly-linked list to make deletion easier.
18 typedef struct allocation_entry {
19 struct allocation_entry * next;
20 struct allocation_entry * prev;
25 static AllocationEntry *alloc_head = NULL;
26 static AllocationEntry *alloc_tail = NULL;
28 static AllocationEntry *find_allocation(void *ptr);
31 /* Allocate some memory and keep track of it. */
33 tracking_malloc(size_t size)
35 AllocationEntry *entry = malloc(sizeof(AllocationEntry));
38 printf("Allocator failure\n");
41 entry->num_bytes = size;
42 entry->allocation = malloc(size);
43 if (entry->allocation == NULL) {
49 /* Add to the list of allocations */
50 if (alloc_head == NULL) {
52 alloc_head = alloc_tail = entry;
54 entry->prev = alloc_tail;
55 alloc_tail->next = entry;
59 return entry->allocation;
62 static AllocationEntry *
63 find_allocation(void *ptr)
65 AllocationEntry *entry;
67 for (entry = alloc_head; entry != NULL; entry = entry->next) {
68 if (entry->allocation == ptr) {
75 /* Free some memory and remove the tracking for it */
77 tracking_free(void *ptr)
79 AllocationEntry *entry;
82 /* There won't be an entry for this */
86 entry = find_allocation(ptr);
88 /* This is the relevant allocation. Unlink it */
89 if (entry->prev != NULL)
90 entry->prev->next = entry->next;
92 alloc_head = entry->next;
93 if (entry->next != NULL)
94 entry->next->prev = entry->prev;
96 alloc_tail = entry->next;
99 printf("Attempting to free unallocated memory at %p\n", ptr);
104 /* Reallocate some memory and keep track of it */
106 tracking_realloc(void *ptr, size_t size)
108 AllocationEntry *entry;
111 /* By definition, this is equivalent to malloc(size) */
112 return tracking_malloc(size);
115 /* By definition, this is equivalent to free(ptr) */
120 /* Find the allocation entry for this memory */
121 entry = find_allocation(ptr);
123 printf("Attempting to realloc unallocated memory at %p\n", ptr);
124 entry = malloc(sizeof(AllocationEntry));
126 printf("Reallocator failure\n");
129 entry->allocation = realloc(ptr, size);
130 if (entry->allocation == NULL) {
135 /* Add to the list of allocations */
137 if (alloc_head == NULL) {
139 alloc_head = alloc_tail = entry;
141 entry->prev = alloc_tail;
142 alloc_tail->next = entry;
146 entry->allocation = realloc(ptr, size);
147 if (entry->allocation == NULL) {
148 /* Realloc semantics say the original is still allocated */
149 entry->allocation = ptr;
154 entry->num_bytes = size;
155 return entry->allocation;
159 tracking_report(void)
161 AllocationEntry *entry;
163 if (alloc_head == NULL)
166 /* Otherwise we have allocations that haven't been freed */
167 for (entry = alloc_head; entry != NULL; entry = entry->next)
169 printf("Allocated %lu bytes at %p\n",
170 (long unsigned)entry->num_bytes, entry->allocation);