/*****************************************************************************/ /* */ /* F I S T : Fast, Industrial-Strength Triangulation */ /* */ /*****************************************************************************/ /* */ /* (C) Martin Held */ /* (C) Universitaet Salzburg, Salzburg, Austria */ /* */ /* This code is not in the public domain. All rights reserved! Please make */ /* sure to read the full copyright statement contained in api_functions.cpp. */ /* */ /*****************************************************************************/ /* */ /* get standard libraries */ /* */ #include #include /* */ /* get my header files */ /* */ #include "fpkernel.h" #include "martin.h" #include "defs.h" /* */ /* prototypes of functions provided in this file */ /* */ void *ReallocateArray(debug_memdef *mem, void *old_ptr, int number, size_t size, const char var_name[]); void FreeMemory(debug_memdef *mem, void **ptr, const char var_name[]); boolean AllMemoryFreed(debug_memdef *mem); unsigned long ReportMaxNumberBytes(debug_memdef *mem); unsigned long ReportCurrNumberBytes(debug_memdef *mem); #ifdef DEBUG_MEMORY boolean IndexOutOfBounds(debug_memdef *mem, void *array_ptr, char var_name[], size_t size, int index); #endif /* DEBUG_MEMORY */ /* */ /* local stuff used for memory debugging */ /* */ #ifdef DEBUG_MEMORY typedef enum { mem_freed, mem_allocated, mem_reallocated } memory_status; void UpdateMemoryStatus(debug_memdef *mem, void *ptr, memory_status status, size_t size, unsigned int high); int SearchMemoryHistory(debug_memdef *mem, void *ptr); void InitDebugMemDefaults(debug_memdef *mem); #endif /* DEBUG_MEMORY */ #ifdef DEBUG_MEMORY void InitDebugMemDefaults(debug_memdef *mem) { mem->curr_memory = 0; mem->max_memory = 0; mem->memory_dbg_cursor = 0; } #endif /* DEBUG_MEMORY */ void *ReallocateArray(debug_memdef *mem, void *old_ptr, int number, size_t size, const char var_name[]) { void *new_ptr; if (old_ptr != (void*)NULL) { #ifdef DEBUG_MEMORY fprintf(stderr, "\nMDebug: "); fprintf(stderr, "Reallocating %d elements of %d bytes for array `%s':", number, (int)size, var_name); fflush(stderr); UpdateMemoryStatus(mem, old_ptr, mem_reallocated, size, number); #endif /* DEBUG_MEMORY */ new_ptr = (void*) realloc((void*) old_ptr, number * size); if (new_ptr == (void*)NULL) throw MEM_ALLOC_FAILED; } else { #ifdef DEBUG_MEMORY fprintf(stderr, "\nMDebug: "); fprintf(stderr, "Allocating %d elements of %d bytes for array `%s':", number, (int)size, var_name); fflush(stderr); #endif /* DEBUG_MEMORY */ new_ptr = (void*) calloc(number, size); if (new_ptr == (void*)NULL) throw MEM_ALLOC_FAILED; } #ifdef DEBUG_MEMORY fprintf(stderr, " done!\n"); fflush(stderr); UpdateMemoryStatus(mem, new_ptr, mem_allocated, size, number); #else (void) mem; (void) var_name; #endif /* DEBUG_MEMORY */ return new_ptr; } #ifdef DEBUG_MEMORY void UpdateMemoryStatus(debug_memdef *mem, void *ptr, memory_status status, size_t size, unsigned int high) { int i; switch(status) { case(mem_allocated): if (mem->memory_dbg_cursor < MAX_MEMORY_CURSOR) { mem->memory_history[mem->memory_dbg_cursor].array_ptr = ptr; mem->memory_history[mem->memory_dbg_cursor].size = size; mem->memory_history[mem->memory_dbg_cursor].high = high; ++mem->memory_dbg_cursor; mem->curr_memory += size * high; if (mem->curr_memory > mem->max_memory) mem->max_memory = mem->curr_memory; } else { throw MEM_TRACKING_EXHAUSTED; } break; case(mem_reallocated): if (ptr != NULL) { i = SearchMemoryHistory(mem, ptr); if (i >= 0) { if (mem->memory_history[i].size != size) { throw MEM_REALLOC_MISMATCH; } mem->curr_memory -= size * mem->memory_history[i].high; mem->memory_history[i].high = 0; } else { throw MEM_TRACKING_MESSED_UP; } } break; case(mem_freed): i = SearchMemoryHistory(mem, ptr); if (i >= 0) { mem->curr_memory -= mem->memory_history[i].size * mem->memory_history[i].high; mem->memory_history[i].high = 0; } else { throw MEM_TRACKING_MESSED_UP; } break; } return; } int SearchMemoryHistory(debug_memdef *mem, void *ptr) { int i; i = mem->memory_dbg_cursor - 1; while (i >= 0) { if (mem->memory_history[i].array_ptr == ptr) return i; --i; } return i; } #endif /* DEBUG_MEMORY */ unsigned long ReportMaxNumberBytes(debug_memdef *mem) { #ifdef DEBUG_MEMORY return mem->max_memory; #else (void) mem; return 0; #endif } unsigned long ReportCurrNumberBytes(debug_memdef *mem) { #ifdef DEBUG_MEMORY return mem->curr_memory; #else (void) mem; return 0; #endif } #ifdef DEBUG_MEMORY boolean IndexOutOfBounds(debug_memdef *mem, void *array_ptr, char var_name[], size_t size, int index) { int i; i = SearchMemoryHistory(mem, array_ptr); if (i >= 0) { if (size != mem->memory_history[i].size) { fprintf(stderr, "*** Bytes per component of array `%s' do not match bytes ", var_name); fprintf(stderr, "specified! ***\n"); fprintf(stderr, " Bytes per component: %d bytes; bytes specified: %d\n", (int)mem->memory_history[i].size, (int)size); fflush(stderr); throw MEM_TYPE_MISMATCH; } return ((index < 0) || (index >= (int) mem->memory_history[i].high)); } else { fprintf(stderr, "*** IndexOutOfBounds: array `%s' has already been ", var_name); fprintf(stderr, "deallocated! ***\n"); fflush(stderr); throw MEM_NULL_POINTER; } return false; } #endif /* DEBUG_MEMORY */ void FreeMemory(debug_memdef *mem, void **ptr, const char var_name[]) { if (*ptr == NULL) { #ifdef DEBUG_MEMORY fprintf(stderr, "FreeMemory() - array `%s' has already been freed!\n", var_name); fflush(stderr); #endif return; } #ifdef DEBUG_MEMORY fprintf(stderr, "\nMDebug: `%s' has been freed\n", var_name); fflush(stderr); UpdateMemoryStatus(mem, *ptr, mem_freed, 0, 0); #else (void) mem; (void) var_name; #endif /* DEBUG_MEMORY */ free(*ptr); *ptr = NULL; return; } boolean AllMemoryFreed(debug_memdef *mem) { #ifdef DEBUG_MEMORY int i; for (i = 0; i < mem->memory_dbg_cursor; ++i) { if (mem->memory_history[i].high != 0) return false; } #else (void) mem; #endif /* DEBUG_MEMORY */ return true; }