void *gf_mem_realloc_tracker(void *ptr, size_t size, const char *filename, int line) { void *ptr_g; int size_prev; if (!ptr) { gf_memory_log(GF_MEMORY_DEBUG, "[MemTracker] realloc() from a null pointer: calling malloc() instead\n"); return gf_mem_malloc_tracker(size, filename, line); } /*a) The return value is NULL if the size is zero and the buffer argument is not NULL. In this case, the original block is freed.*/ if (!size) { gf_memory_log(GF_MEMORY_DEBUG, "[MemTracker] realloc() with a null size: calling free() instead\n"); gf_mem_free_tracker(ptr, filename, line); return NULL; } ptr_g = REALLOC(ptr, size); if (!ptr_g) { /*b) The return value is NULL if there is not enough available memory to expand the block to the given size. In this case, the original block is unchanged.*/ gf_memory_log(GF_MEMORY_ERROR, "[MemTracker] realloc() has returned a NULL pointer\n"); assert(0); } else { size_prev = unregister_address(ptr, filename, line); register_address(ptr_g, size, filename, line); gf_memory_log(GF_MEMORY_DEBUG, "[MemTracker] realloc %3d (instead of %3d) bytes at %p (instead of %p)\n in file %s at line %d\n", size, size_prev, ptr_g, ptr, filename, line); } return ptr_g; }
void gf_mem_free_tracker(void *ptr, const char *filename, int line) { int size_prev; if (ptr && (size_prev=unregister_address(ptr, filename, line))) { gf_memory_log(GF_MEMORY_DEBUG, "[MemTracker] free %3d bytes at %p in:\n", size_prev, ptr); gf_memory_log(GF_MEMORY_DEBUG, " file %s at line %d\n" , filename, line); FREE(ptr); } }
void *gf_mem_malloc_tracker(size_t size, const char *filename, int line) { void *ptr = MALLOC(size); if (!ptr) { gf_memory_log(GF_MEMORY_ERROR, "[MemTracker] malloc() has returned a NULL pointer\n"); assert(0); } else { register_address(ptr, size, filename, line); } gf_memory_log(GF_MEMORY_DEBUG, "[MemTracker] malloc %3d bytes at %p\n in file %s at line %d\n", size, ptr, filename, line); return ptr; }
void *gf_mem_calloc_tracker(size_t num, size_t size_of, char *filename, int line) { size_t size = num*size_of; void *ptr = CALLOC(num, size_of); if (!ptr) { gf_memory_log(GF_MEMORY_ERROR, "[MemTracker] calloc() has returned a NULL pointer\n"); assert(0); } else { register_address(ptr, size, filename, line); } gf_memory_log(GF_MEMORY_DEBUG, "[MemTracker] calloc %3d bytes at 0x%08X\n in file %s at line %d\n", size, ptr, filename, line); return ptr; }
/*memory ownership to the caller*/ static void store_backtrace(char *s_backtrace) { size_t i, size, bt_idx=0; void *stack[STACK_PRINT_SIZE+STACK_FIRST_IDX]; char **messages; size = backtrace(stack, STACK_PRINT_SIZE+STACK_FIRST_IDX); messages = backtrace_symbols(stack, size); for (i=STACK_FIRST_IDX; i<size && messages!=NULL; ++i) { int bt_len = strlen(messages[i]) + 10; int len; if (bt_idx + bt_len > STACK_PRINT_SIZE*SYMBOL_MAX_SIZE) { gf_memory_log(GF_MEMORY_WARNING, "[MemoryInfo] Not enough space to hold backtrace - truncating\n"); break; } len = snprintf(s_backtrace+bt_idx, SYMBOL_MAX_SIZE-1, "\t%02zu %s", i, messages[i]); if (len<0) len = SYMBOL_MAX_SIZE-1; s_backtrace[bt_idx+len]='\n'; bt_idx += (len+1); } assert(bt_idx < STACK_PRINT_SIZE*SYMBOL_MAX_SIZE); s_backtrace[bt_idx-1] = '\0'; free(messages); }
/*memory ownership to the caller*/ static void store_backtrace(char *s_backtrace) { void *stack[STACK_PRINT_SIZE]; size_t i, frames, bt_idx = 0; SYMBOL_INFO *symbol; HANDLE process; process = GetCurrentProcess(); SymInitialize(process, NULL, TRUE); symbol = (SYMBOL_INFO*)_alloca(sizeof(SYMBOL_INFO) + SYMBOL_MAX_SIZE); symbol->MaxNameLen = SYMBOL_MAX_SIZE-1; symbol->SizeOfStruct = sizeof(SYMBOL_INFO); frames = CaptureStackBackTrace(STACK_FIRST_IDX, STACK_PRINT_SIZE, stack, NULL); for (i=0; i<frames; i++) { int len; int bt_len; char *symbol_name = "unresolved"; SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol); if (symbol->Name) symbol_name = (char*)symbol->Name; bt_len = (int) strlen(symbol_name) + 10; if (bt_idx + bt_len > STACK_PRINT_SIZE*SYMBOL_MAX_SIZE) { gf_memory_log(GF_MEMORY_WARNING, "[MemoryInfo] Not enough space to hold backtrace - truncating\n"); break; } len = _snprintf(s_backtrace+bt_idx, SYMBOL_MAX_SIZE-1, "\t%02u 0x%I64X %s", (unsigned int) (frames-i-1), symbol->Address, symbol_name); if (len<0) len = SYMBOL_MAX_SIZE-1; s_backtrace[bt_idx+len]='\n'; bt_idx += (len+1); } assert(bt_idx < STACK_PRINT_SIZE*SYMBOL_MAX_SIZE); s_backtrace[bt_idx-1] = '\0'; }