Annotation of src/external/mit/expat/dist/tests/memcheck.c, Revision 1.1.1.1.6.2
1.1.1.1.6.2! snj 1: /* Copyright (c) 2017 The Expat Maintainers
! 2: * Copying is permitted under the MIT license. See the file COPYING
! 3: * for details.
! 4: *
! 5: * memcheck.c : debug allocators for the Expat test suite
! 6: */
! 7:
! 8: #include <stdio.h>
! 9: #include <stdlib.h>
! 10: #include "memcheck.h"
! 11:
! 12:
! 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.
! 16: */
! 17:
! 18: typedef struct allocation_entry {
! 19: struct allocation_entry * next;
! 20: struct allocation_entry * prev;
! 21: void * allocation;
! 22: size_t num_bytes;
! 23: } AllocationEntry;
! 24:
! 25: static AllocationEntry *alloc_head = NULL;
! 26: static AllocationEntry *alloc_tail = NULL;
! 27:
! 28: static AllocationEntry *find_allocation(void *ptr);
! 29:
! 30:
! 31: /* Allocate some memory and keep track of it. */
! 32: void *
! 33: tracking_malloc(size_t size)
! 34: {
! 35: AllocationEntry *entry = malloc(sizeof(AllocationEntry));
! 36:
! 37: if (entry == NULL) {
! 38: printf("Allocator failure\n");
! 39: return NULL;
! 40: }
! 41: entry->num_bytes = size;
! 42: entry->allocation = malloc(size);
! 43: if (entry->allocation == NULL) {
! 44: free(entry);
! 45: return NULL;
! 46: }
! 47: entry->next = NULL;
! 48:
! 49: /* Add to the list of allocations */
! 50: if (alloc_head == NULL) {
! 51: entry->prev = NULL;
! 52: alloc_head = alloc_tail = entry;
! 53: } else {
! 54: entry->prev = alloc_tail;
! 55: alloc_tail->next = entry;
! 56: alloc_tail = entry;
! 57: }
! 58:
! 59: return entry->allocation;
! 60: }
! 61:
! 62: static AllocationEntry *
! 63: find_allocation(void *ptr)
! 64: {
! 65: AllocationEntry *entry;
! 66:
! 67: for (entry = alloc_head; entry != NULL; entry = entry->next) {
! 68: if (entry->allocation == ptr) {
! 69: return entry;
! 70: }
! 71: }
! 72: return NULL;
! 73: }
! 74:
! 75: /* Free some memory and remove the tracking for it */
! 76: void
! 77: tracking_free(void *ptr)
! 78: {
! 79: AllocationEntry *entry;
! 80:
! 81: if (ptr == NULL) {
! 82: /* There won't be an entry for this */
! 83: return;
! 84: }
! 85:
! 86: entry = find_allocation(ptr);
! 87: if (entry != NULL) {
! 88: /* This is the relevant allocation. Unlink it */
! 89: if (entry->prev != NULL)
! 90: entry->prev->next = entry->next;
! 91: else
! 92: alloc_head = entry->next;
! 93: if (entry->next != NULL)
! 94: entry->next->prev = entry->prev;
! 95: else
! 96: alloc_tail = entry->next;
! 97: free(entry);
! 98: } else {
! 99: printf("Attempting to free unallocated memory at %p\n", ptr);
! 100: }
! 101: free(ptr);
! 102: }
! 103:
! 104: /* Reallocate some memory and keep track of it */
! 105: void *
! 106: tracking_realloc(void *ptr, size_t size)
! 107: {
! 108: AllocationEntry *entry;
! 109:
! 110: if (ptr == NULL) {
! 111: /* By definition, this is equivalent to malloc(size) */
! 112: return tracking_malloc(size);
! 113: }
! 114: if (size == 0) {
! 115: /* By definition, this is equivalent to free(ptr) */
! 116: tracking_free(ptr);
! 117: return NULL;
! 118: }
! 119:
! 120: /* Find the allocation entry for this memory */
! 121: entry = find_allocation(ptr);
! 122: if (entry == NULL) {
! 123: printf("Attempting to realloc unallocated memory at %p\n", ptr);
! 124: entry = malloc(sizeof(AllocationEntry));
! 125: if (entry == NULL) {
! 126: printf("Reallocator failure\n");
! 127: return NULL;
! 128: }
! 129: entry->allocation = realloc(ptr, size);
! 130: if (entry->allocation == NULL) {
! 131: free(entry);
! 132: return NULL;
! 133: }
! 134:
! 135: /* Add to the list of allocations */
! 136: entry->next = NULL;
! 137: if (alloc_head == NULL) {
! 138: entry->prev = NULL;
! 139: alloc_head = alloc_tail = entry;
! 140: } else {
! 141: entry->prev = alloc_tail;
! 142: alloc_tail->next = entry;
! 143: alloc_tail = entry;
! 144: }
! 145: } else {
! 146: entry->allocation = realloc(ptr, size);
! 147: if (entry->allocation == NULL) {
! 148: /* Realloc semantics say the original is still allocated */
! 149: entry->allocation = ptr;
! 150: return NULL;
! 151: }
! 152: }
! 153:
! 154: entry->num_bytes = size;
! 155: return entry->allocation;
! 156: }
! 157:
! 158: int
! 159: tracking_report(void)
! 160: {
! 161: AllocationEntry *entry;
! 162:
! 163: if (alloc_head == NULL)
! 164: return 1;
! 165:
! 166: /* Otherwise we have allocations that haven't been freed */
! 167: for (entry = alloc_head; entry != NULL; entry = entry->next)
! 168: {
! 169: printf("Allocated %lu bytes at %p\n",
! 170: entry->num_bytes, entry->allocation);
! 171: }
! 172: return 0;
! 173: }
CVSweb <webmaster@jp.NetBSD.org>