From a335f1fd00de05a251a1632931c4d74c545b1fba Mon Sep 17 00:00:00 2001 From: Lightning11wins Date: Wed, 3 Dec 2025 16:24:59 -0700 Subject: [PATCH 1/3] Improve code clarity with minimal logic modifications. --- centrallix-lib/include/newmalloc.h | 10 +- centrallix-lib/src/newmalloc.c | 753 ++++++++++++++--------------- 2 files changed, 373 insertions(+), 390 deletions(-) diff --git a/centrallix-lib/include/newmalloc.h b/centrallix-lib/include/newmalloc.h index 6022e72e3..038df686a 100644 --- a/centrallix-lib/include/newmalloc.h +++ b/centrallix-lib/include/newmalloc.h @@ -32,7 +32,7 @@ typedef struct _ov int Magic; struct _ov *Next; } - Overlay,*pOverlay; + Overlay, *pOverlay; #ifdef NMMALLOC_DEBUG #define BLK_LEAK_CHECK 1 @@ -70,15 +70,15 @@ void nmSetErrFunction(int (*error_fn)()); void nmClear(); void nmCheckAll(); // checks for buffer overflows void* nmMalloc(int size); -void nmFree(void* ptr,int size); +void nmFree(void* ptr, int size); void nmStats(); -void nmRegister(int size,char* name); +void nmRegister(int size, char* name); void nmDebug(); void nmDeltas(); void* nmSysMalloc(int size); void nmSysFree(void* ptr); -void* nmSysRealloc(void* ptr, int newsize); -char* nmSysStrdup(const char* ptr); +void* nmSysRealloc(void* ptr, int new_size); +char* nmSysStrdup(const char* str); void nmEnableTagging(); void nmRegisterTagID(int tag_id, char* name); diff --git a/centrallix-lib/src/newmalloc.c b/centrallix-lib/src/newmalloc.c index 32c02b85d..ffa3daf80 100644 --- a/centrallix-lib/src/newmalloc.c +++ b/centrallix-lib/src/newmalloc.c @@ -1,13 +1,3 @@ -#ifdef HAVE_CONFIG_H -#include "cxlibconfig-internal.h" -#endif -#include -#include -#include -#include -#include "magic.h" -#include "newmalloc.h" - /************************************************************************/ /* Centrallix Application Server System */ /* Centrallix Base Library */ @@ -18,8 +8,8 @@ /* GNU Lesser General Public License, Version 2.1, contained in the */ /* included file "COPYING". */ /* */ -/* Module: NewMalloc memory manager (newmalloc.c, .h) */ -/* Author: Greg Beeley (GRB) */ +/* Module: NewMalloc memory manager (newmalloc.c, .h) */ +/* Author: Greg Beeley (GRB) */ /* */ /* Description: This module provides block-caching memory allocation */ /* and debugging services, to help find memory leaks as */ @@ -36,19 +26,20 @@ /* all.... */ /************************************************************************/ +#ifdef HAVE_CONFIG_H +#include "cxlibconfig-internal.h" +#endif + +#include +#include +#include +#include +#include + +#include "magic.h" +#include "newmalloc.h" -/** define BUFFER_OVERFLOW_CHECKING for buffer overflow checking -*** this works off of magic numbers in the 4 bytes on either end -*** of the buffer that is returned to the user, at the cost of -*** 16 bytes of memory per buffer, and a full scan of the list -*** of allocated memory twice per nmMalloc() or nmFree() call -*** -*** the check can be made at any time from normal code by calling: -*** nmCheckAll() -*** -- this functions is still defined if BUFFER_OVERFLOW_CHECKING is -*** not defined, but it becomes a NOOP -**/ #ifdef BUFFER_OVERFLOW_CHECKING typedef struct _mem { @@ -84,7 +75,7 @@ void* blks[MAX_BLOCKS]; int blksiz[MAX_BLOCKS]; #endif -int isinit=0; +bool is_init = false; int (*err_fn)() = NULL; int nmsys_outcnt[MAX_SIZE+1]; @@ -104,47 +95,55 @@ pRegisteredBlockType blknames[MAX_SIZE+1]; void nmInitialize() { - int i; - - for(i=0;i<=MAX_SIZE;i++) lists[i]=NULL; - for(i=0;i<=MAX_SIZE;i++) listcnt[i] = 0; - for(i=0;i<=MAX_SIZE;i++) outcnt[i] = 0; - for(i=0;i<=MAX_SIZE;i++) outcnt_delta[i] = 0; - for(i=0;i<=MAX_SIZE;i++) blknames[i] = NULL; - for(i=0;i<=MAX_SIZE;i++) usagecnt[i] = 0; - for(i=0;i<=MAX_SIZE;i++) nmsys_outcnt[i] = 0; - for(i=0;i<=MAX_SIZE;i++) nmsys_outcnt_delta[i] = 0; -#ifdef BLK_LEAK_CHECK - for(i=0;imagic_start!=MGK_MEMSTART) + int ret = 0; + + if (mem->magic_start != MGK_MEMSTART) { - printf("bad magic_start at %p (%p) -- 0x%08x != 0x%08x\n",MEMDATA(mem),mem,mem->magic_start,MGK_MEMSTART); + fprintf(stderr, + "Bad magic_start at %p (%p) -- 0x%08x != 0x%08x\n", + MEMDATA(mem), mem, mem->magic_start, MGK_MEMSTART + ); ret = -1; } - if(ENDMAGIC(mem)!=MGK_MEMEND) + + if (ENDMAGIC(mem) != MGK_MEMEND) { - printf("bad magic_end at %p (%p) -- 0x%08x != 0x%08x\n",MEMDATA(mem),mem,ENDMAGIC(mem),MGK_MEMEND); + fprintf(stderr, + "Bad magic_end at %p (%p) -- 0x%08x != 0x%08x\n", + MEMDATA(mem), mem, ENDMAGIC(mem), MGK_MEMEND + ); ret = -1; } + return ret; } #endif @@ -152,79 +151,74 @@ nmCheckItem(pMemStruct mem) void nmCheckAll() { -#ifdef BUFFER_OVERFLOW_CHECKING - pMemStruct mem; - int ret=0; - mem=startMemList; - while(mem) - { - if(nmCheckItem(mem)==-1) - ret=-1; - mem=mem->next; - } - if(ret==-1) + #ifdef BUFFER_OVERFLOW_CHECKING + int ret = 0; + + for (pMemStruct mem = startMemList; mem != NULL; mem = mem->next) + if (nmCheckItem(mem) == -1) ret = -1; + + if (ret == -1) { printf("causing segfault to halt.......\n"); - *(int*)NULL=0; + *(int*)NULL = 0; } -#endif + #endif } #ifdef BUFFER_OVERFLOW_CHECKING void* nmDebugMalloc(int size) { - pMemStruct tmp; - - tmp = (pMemStruct)malloc(size+EXTRA_MEM); - if(!tmp) - return NULL; + pMemStruct tmp = (pMemStruct)malloc(size + EXTRA_MEM); + if(tmp == NULL) return NULL; + + tmp->size = size; + tmp->magic_start = MGK_MEMSTART; + ENDMAGIC(tmp) = MGK_MEMEND; + tmp->next = startMemList; - startMemList=tmp; - tmp->size=size; - tmp->magic_start=MGK_MEMSTART; - ENDMAGIC(tmp)=MGK_MEMEND; + startMemList = tmp; return (void*)MEMDATA(tmp); } void -nmDebugFree(void *ptr) +nmDebugFree(void* ptr) { - pMemStruct tmp; - pMemStruct prev; - - tmp = MEMDATATOSTRUCT(ptr); + pMemStruct tmp = MEMDATATOSTRUCT(ptr); + nmCheckItem(tmp); - if(tmp==startMemList) + + if (tmp == startMemList) { - startMemList=tmp->next; + startMemList = tmp->next; } else { - prev = startMemList; - while(prev->next != tmp) - prev=prev->next; - prev->next=tmp->next; + pMemStruct prev = startMemList; + while (prev->next != tmp) + prev = prev->next; + + prev->next = tmp->next; } + free(tmp); } void* -nmDebugRealloc(void *ptr,int newsize) +nmDebugRealloc(void* ptr, int new_size) { - void *newptr; - int oldsize; - - if(!ptr) - return nmDebugMalloc(newsize); - newptr=(void*)nmDebugMalloc(newsize); - if(!newptr) - return NULL; - oldsize=MEMDATATOSTRUCT(ptr)->size; - memmove(newptr,ptr,oldsize); + if (ptr == NULL) return nmDebugMalloc(new_size); + + void* new_ptr = (void*)nmDebugMalloc(new_size); + if (new_ptr == NULL) return NULL; + + int old_size = MEMDATATOSTRUCT(ptr)->size; + memmove(new_ptr, ptr, old_size); + nmDebugFree(ptr); - return newptr; + + return new_ptr; } #else #define nmDebugMalloc(size) malloc(size) @@ -232,112 +226,109 @@ nmDebugRealloc(void *ptr,int newsize) #define nmDebugRealloc(ptr,size) realloc(ptr,size) #endif + void nmSetErrFunction(int (*error_fn)()) { err_fn = error_fn; - return; } + void nmClear() { - int i; - pOverlay ov,del; - - if (!isinit) nmInitialize(); - - for(i=MIN_SIZE;i<=MAX_SIZE;i++) + if (!is_init) nmInitialize(); + + for (size_t size = MIN_SIZE; size <= MAX_SIZE; size++) + { + pOverlay ov = lists[size]; + while (ov != NULL) { - ov = lists[i]; - while(ov) - { - del = ov; - ov = ov->Next; - nmDebugFree(del); - } - lists[i] = NULL; + pOverlay del = ov; + ov = ov->Next; + nmDebugFree(del); } - - return; + lists[size] = NULL; + } } + void* nmMalloc(int size) { void* tmp; -#ifdef BLK_LEAK_CHECK - int i; -#endif - - if (!isinit) nmInitialize(); - -#ifdef GLOBAL_BLK_COUNTING - nmMallocCnt++; -#endif - -#ifdef BUFFER_OVERFLOW_CHECKING - nmCheckAll(); -#endif - - if (size <= MAX_SIZE && size >= MIN_SIZE) - { -#ifdef SIZED_BLK_COUNTING - outcnt[size]++; - usagecnt[size]++; -#endif - if (lists[size] == NULL) - { - tmp = (void*)nmDebugMalloc(size); - } - else - { -#ifdef GLOBAL_BLK_COUNTING - nmMallocHits++; -#endif - tmp = lists[size]; - ASSERTMAGIC(tmp,MGK_FREEMEM); - lists[size]=lists[size]->Next; -#ifdef SIZED_BLK_COUNTING - listcnt[size]--; -#endif - } - } - else + if (!is_init) nmInitialize(); + + #ifdef GLOBAL_BLK_COUNTING + nmMallocCnt++; + #endif + + #ifdef BUFFER_OVERFLOW_CHECKING + nmCheckAll(); + #endif + + if (MIN_SIZE <= size && size <= MAX_SIZE) + { + #ifdef SIZED_BLK_COUNTING + outcnt[size]++; + usagecnt[size]++; + #endif + + if (lists[size] == NULL) { -#ifdef GLOBAL_BLK_COUNTING - nmMallocTooBig++; - if (size > nmMallocLargest) nmMallocLargest = size; -#endif tmp = (void*)nmDebugMalloc(size); } - - if (!tmp) - { - if (err_fn) err_fn("Insufficient system memory for operation."); - } else { - if (size >= MIN_SIZE) - OVERLAY(tmp)->Magic = MGK_ALLOCMEM; + #ifdef GLOBAL_BLK_COUNTING + nmMallocHits++; + #endif + + tmp = lists[size]; + ASSERTMAGIC(tmp, MGK_FREEMEM); + lists[size] = lists[size]->Next; + + #ifdef SIZED_BLK_COUNTING + listcnt[size]--; + #endif } - -#ifdef BUFFER_OVERFLOW_CHECKING - nmCheckAll(); -#endif - -#ifdef BLK_LEAK_CHECK - for(i=0;i nmMallocLargest) nmMallocLargest = size; + #endif + + tmp = (void*)nmDebugMalloc(size); + } + + if (tmp == NULL) + { + if (err_fn) err_fn("Insufficient system memory for operation."); + } + else + { + if (size >= MIN_SIZE) + OVERLAY(tmp)->Magic = MGK_ALLOCMEM; + } + + #ifdef BUFFER_OVERFLOW_CHECKING + nmCheckAll(); + #endif + + #ifdef BLK_LEAK_CHECK + for (int i = 0; i < MAX_BLOCKS; i++) + { + if (blks[i] == NULL) { - if (blks[i] == NULL) - { - blks[i] = tmp; - blksiz[i] = size; - break; - } + blks[i] = tmp; + blksiz[i] = size; + break; } -#endif - + } + #endif + return tmp; } @@ -345,270 +336,262 @@ nmMalloc(int size) void nmFree(void* ptr, int size) { -#ifndef NO_BLK_CACHE -#ifdef DUP_FREE_CHECK - pOverlay tmp; -#endif -#endif -#ifdef BLK_LEAK_CHECK - int i; -#endif - - if (size >= MIN_SIZE) - ASSERTNOTMAGIC(ptr,MGK_FREEMEM); - - if (!ptr) return; - - if (!isinit) nmInitialize(); - -#ifdef GLOBAL_BLK_COUNTING - nmFreeCnt++; -#endif - -#ifdef BUFFER_OVERFLOW_CHECKING - nmCheckAll(); -#endif - -#ifdef BLK_LEAK_CHECK - for(i=0;i= MIN_SIZE) + ASSERTNOTMAGIC(ptr, MGK_FREEMEM); + + if (ptr == NULL) return; + + #ifdef GLOBAL_BLK_COUNTING + nmFreeCnt++; + #endif + + #ifdef BUFFER_OVERFLOW_CHECKING + nmCheckAll(); + #endif + + #ifdef BLK_LEAK_CHECK + for (int i = 0; i < MAX_BLOCKS; i++) + { + if (blks[i] == ptr) { - if (blks[i] == ptr) - { - blks[i] = NULL; - blksiz[i] = 0; - break; - } + blks[i] = NULL; + blksiz[i] = 0; + break; } -#endif - -#ifndef NO_BLK_CACHE - if (size <= MAX_SIZE && size >= MIN_SIZE) + } + #endif + + #ifndef NO_BLK_CACHE + if (size <= MAX_SIZE && size >= MIN_SIZE) + { + #ifdef DUP_FREE_CHECK + for (pOverlay tmp = lists[size]; tmp != NULL; tmp = OVERLAY(tmp)->Next) { -#ifdef DUP_FREE_CHECK - tmp = lists[size]; - while(tmp) - { - ASSERTMAGIC(OVERLAY(tmp),MGK_FREEMEM); - if (OVERLAY(tmp) == OVERLAY(ptr)) - { - printf("Duplicate nmFree()!!! Size = %d, Address = %p\n",size,ptr); - if (err_fn) err_fn("Internal error - duplicate nmFree() occurred."); - return; - } - tmp = OVERLAY(tmp)->Next; + ASSERTMAGIC(OVERLAY(tmp),MGK_FREEMEM); + if (OVERLAY(tmp) == OVERLAY(ptr)) + { + printf("Duplicate nmFree()!!! Size = %d, Address = %p\n", size, ptr); + if (err_fn) err_fn("Internal error - duplicate nmFree() occurred."); + return; } -#endif -#ifdef SIZED_BLK_COUNTING - outcnt[size]--; -#endif - OVERLAY(ptr)->Next = lists[size]; - lists[size] = OVERLAY(ptr); -#ifdef SIZED_BLK_COUNTING - listcnt[size]++; -#endif - OVERLAY(ptr)->Magic = MGK_FREEMEM; - } - else - { -#endif - nmDebugFree(ptr); -#ifndef NO_BLK_CACHE } -#endif - -#ifdef BUFFER_OVERFLOW_CHECKING - nmCheckAll(); -#endif - - return; + #endif + + OVERLAY(ptr)->Magic = MGK_FREEMEM; + OVERLAY(ptr)->Next = lists[size]; + lists[size] = OVERLAY(ptr); + ptr = NULL; + + #ifdef SIZED_BLK_COUNTING + outcnt[size]--; + listcnt[size]++; + #endif + } + #endif + + if (ptr != NULL) + { + nmDebugFree(ptr); + ptr = NULL; + } + + #ifdef BUFFER_OVERFLOW_CHECKING + nmCheckAll(); + #endif } void nmStats() { - - if (!isinit) nmInitialize(); - - printf("NewMalloc subsystem statistics:\n"); - printf(" nmMalloc: %d calls, %d hits (%3.3f%%)\n", - nmMallocCnt, - nmMallocHits, - (float)nmMallocHits/(float)nmMallocCnt*100.0); - printf(" nmFree: %d calls\n", nmFreeCnt); - printf(" bigblks: %d too big, %d largest size\n\n", - nmMallocTooBig, - nmMallocLargest); - - return; + if (!is_init) nmInitialize(); + + printf( + "NewMalloc subsystem statistics:\n" + " nmMalloc: %d calls, %d hits (%3.3f%%)\n" + " nmFree: %d calls\n" + " bigblks: %d too big, %d largest size\n\n", + nmMallocCnt, nmMallocHits, (float)nmMallocHits / (float)nmMallocCnt * 100.0, + nmFreeCnt, + nmMallocTooBig, nmMallocLargest + ); } void -nmRegister(int size,char* name) +nmRegister(int size, char* name) { pRegisteredBlockType blk; - - if (size > MAX_SIZE) return; - - blk = (pRegisteredBlockType)malloc(sizeof(RegisteredBlockType)); - blk->Next = blknames[size]; - blk->Size = size; - strcpy(blk->Name,name); - blknames[size] = blk; - blk->Magic = MGK_REGISBLK; - - return; + + if (size > MAX_SIZE) return; + + blk = (pRegisteredBlockType)malloc(sizeof(RegisteredBlockType)); + if (blk == NULL) return; + blk->Next = blknames[size]; + blknames[size] = blk; + + blk->Magic = MGK_REGISBLK; + blk->Size = size; + strcpy(blk->Name, name); } void nmDebug() { - int i; - pRegisteredBlockType blk; - - printf("size\tout\tcache\tusage\tnames\n"); - for(i=MIN_SIZE;iName); - blk = blk->Next; - } - printf("\n"); - } - } - printf("\n-----\n"); - printf("size\toutcnt\n-------\t-------\n"); - for(i=MIN_SIZE;i<=MAX_SIZE;i++) + printf("size\tout\tcache\tusage\tnames\n"); + + for (size_t size = MIN_SIZE; size < MAX_SIZE; size++) + { + if (usagecnt[size] == 0) continue; + + printf("%ld\t%d\t%d\t%d\t", size, outcnt[size], listcnt[size], usagecnt[size]); + + pRegisteredBlockType blk = blknames[size]; + while(blk) { - if (nmsys_outcnt[i]) printf("%d\t%d\n",i,nmsys_outcnt[i]); + ASSERTMAGIC(blk,MGK_REGISBLK); + printf("%s ", blk->Name); + blk = blk->Next; } + printf("\n"); - - return; + } + + printf("\n-----\n"); + printf("size\toutcnt\n-------\t-------\n"); + + for (size_t size = MIN_SIZE; size <= MAX_SIZE; size++) + { + if (nmsys_outcnt[size] == 0) continue; + + printf("%ld\t%d\n", size, nmsys_outcnt[size]); + } + printf("\n"); } void nmDeltas() { - int i, total; - pRegisteredBlockType blk; - - total = 0; - printf("size\tdelta\tnames\n-------\t-------\t-------\n"); - for(i=MIN_SIZE;i<=MAX_SIZE;i++) - { - if (outcnt[i] != outcnt_delta[i]) - { - printf("%d\t%d\t",i,outcnt[i] - outcnt_delta[i]); - total += (i * (outcnt[i] - outcnt_delta[i])); - blk = blknames[i]; - while(blk) - { - ASSERTMAGIC(blk,MGK_REGISBLK); - printf("%s ", blk->Name); - blk = blk->Next; - } - printf("\n"); - outcnt_delta[i] = outcnt[i]; - } - } - printf("\nsize\tdelta\n-------\t-------\n"); - for(i=MIN_SIZE;i<=MAX_SIZE;i++) + printf("size\tdelta\tnames\n-------\t-------\t-------\n"); + + int total_delta = 0; + for (size_t size = MIN_SIZE; size <= MAX_SIZE; size++) + { + if (outcnt[size] == outcnt_delta[size]) continue; + + printf("%ld\t%d\t", size, outcnt[size] - outcnt_delta[size]); + total_delta += (size * (outcnt[size] - outcnt_delta[size])); + + pRegisteredBlockType blk = blknames[size]; + while(blk) { - if (nmsys_outcnt[i] != nmsys_outcnt_delta[i]) - { - printf("%d\t%d\n",i,nmsys_outcnt[i] - nmsys_outcnt_delta[i]); - total += (i * (nmsys_outcnt[i] - nmsys_outcnt_delta[i])); - nmsys_outcnt_delta[i] = nmsys_outcnt[i]; - } + ASSERTMAGIC(blk,MGK_REGISBLK); + printf("%s ", blk->Name); + blk = blk->Next; } + printf("\n"); - printf("delta %d total bytes\n", total); - - return; + + outcnt_delta[size] = outcnt[size]; + } + + printf("\nsize\tdelta\n-------\t-------\n"); + for (size_t size = MIN_SIZE; size <= MAX_SIZE; size++) + { + if (nmsys_outcnt[size] != nmsys_outcnt_delta[size]) continue; + + printf("%ld\t%d\n", size, nmsys_outcnt[size] - nmsys_outcnt_delta[size]); + total_delta += (size * (nmsys_outcnt[size] - nmsys_outcnt_delta[size])); + nmsys_outcnt_delta[size] = nmsys_outcnt[size]; + } + printf("\n"); + + printf("delta %d total bytes\n", total_delta); } void* nmSysMalloc(int size) { -#ifdef NM_USE_SYSMALLOC - char* ptr; - ptr = (char*)nmDebugMalloc(size+sizeof(int)); - if (!ptr) return NULL; + #ifndef NM_USE_SYSMALLOC + return (void*)nmDebugMalloc(size); + #else + + char* ptr = (char*)nmDebugMalloc(sizeof(int) + size); + if (ptr == NULL) return NULL; + *(int*)ptr = size; -#ifdef SIZED_BLK_COUNTING + + #ifdef SIZED_BLK_COUNTING if (size > 0 && size <= MAX_SIZE) nmsys_outcnt[size]++; -#endif - return (void*)(ptr+sizeof(int)); -#else - return (void*)nmDebugMalloc(size); -#endif + #endif + + return (void*)(sizeof(int) + ptr); + #endif } + void nmSysFree(void* ptr) { -#ifdef NM_USE_SYSMALLOC -#ifdef SIZED_BLK_COUNTING + #ifndef NM_USE_SYSMALLOC + nmDebugFree(ptr); + #else + + #ifdef SIZED_BLK_COUNTING int size; size = *(int*)(((char*)ptr)-sizeof(int)); if (size > 0 && size <= MAX_SIZE) nmsys_outcnt[size]--; -#endif - nmDebugFree(((char*)ptr)-sizeof(int)); -#else - nmDebugFree(ptr); -#endif + #endif + + nmDebugFree(((char*)ptr) - sizeof(int)); + #endif return; } + void* -nmSysRealloc(void* ptr, int newsize) +nmSysRealloc(void* ptr, int new_size) { -#ifdef NM_USE_SYSMALLOC -#ifdef SIZED_BLK_COUNTING - int size; -#endif - char* newptr; - if (!ptr) return nmSysMalloc(newsize); -#ifdef SIZED_BLK_COUNTING - size = *(int*)(((char*)ptr)-sizeof(int)); -#endif - newptr = (char*)nmDebugRealloc((((char*)ptr)-sizeof(int)), newsize+sizeof(int)); - if (!newptr) return NULL; -#ifdef SIZED_BLK_COUNTING - if (size > 0 && size <= MAX_SIZE) nmsys_outcnt[size]--; -#endif - *(int*)newptr = newsize; -#ifdef SIZED_BLK_COUNTING - if (newsize > 0 && newsize <= MAX_SIZE) nmsys_outcnt[newsize]++; -#endif - return (void*)(newptr+sizeof(int)); -#else - return (void*)nmDebugRealloc(ptr,newsize); -#endif + #ifndef NM_USE_SYSMALLOC + return (void*)nmDebugRealloc(ptr, new_size); + #else + + if (ptr == NULL) return nmSysMalloc(new_size); + + char* newptr = (char*)nmDebugRealloc((((char*)ptr) - sizeof(int)), sizeof(int) + new_size); + if (newptr == NULL) return NULL; + + *(int*)newptr = new_size; + + #ifdef SIZED_BLK_COUNTING + int size = *(int*)(((char*)ptr)-sizeof(int)); + if (0 < size && size <= MAX_SIZE) nmsys_outcnt[size]--; + if (0 < new_size && new_size <= MAX_SIZE) nmsys_outcnt[new_size]++; + #endif + + return (void*)(sizeof(int) + newptr); + #endif } + char* -nmSysStrdup(const char* ptr) +nmSysStrdup(const char* str) { -#ifdef NM_USE_SYSMALLOC - char* newptr; - int n = strlen(ptr); - newptr = (char*)nmSysMalloc(n+1); - if (!newptr) return NULL; - memcpy(newptr,ptr,n+1); - return newptr; -#else - return strdup(ptr); -#endif + #ifndef NM_USE_SYSMALLOC + return strdup(str); + #else + + size_t n = strlen(str) + 1u; + char* new_str = (char*)nmSysMalloc(n); + if (new_str == NULL) return NULL; + + memcpy(new_str, str, n); + + return new_str; + #endif } From c976819016ff9735dbfcd7b638affdeaf56a586d Mon Sep 17 00:00:00 2001 From: Lightning11wins Date: Wed, 3 Dec 2025 17:14:13 -0700 Subject: [PATCH 2/3] Add code comments. --- centrallix-lib/include/newmalloc.h | 10 +- centrallix-lib/src/newmalloc.c | 227 ++++++++++++++++++++++++++++- 2 files changed, 224 insertions(+), 13 deletions(-) diff --git a/centrallix-lib/include/newmalloc.h b/centrallix-lib/include/newmalloc.h index 038df686a..60b2d8a2e 100644 --- a/centrallix-lib/include/newmalloc.h +++ b/centrallix-lib/include/newmalloc.h @@ -44,11 +44,10 @@ typedef struct _ov #define SIZED_BLK_COUNTING 1 #endif -/** nmMalloc block caching causes Valgrind to lose track of what call - ** stack actually allocated the block to begin with. So if we're using - ** valgrind, turn off block caching altogether, and make the nmSysXyz() calls - ** just pass-throughs. - **/ +/*** nmMalloc block caching causes Valgrind to lose track of the call stack + *** where the developer allocated the block. If we are using Valgrind, this + *** caching is disabled. ALso, the nmSysXyz() call are simply pass-throughs. + ***/ #ifdef USING_VALGRIND #define NO_BLK_CACHE 1 #undef NM_USE_SYSMALLOC @@ -80,6 +79,7 @@ void nmSysFree(void* ptr); void* nmSysRealloc(void* ptr, int new_size); char* nmSysStrdup(const char* str); +/** Tagging system (not implemented). **/ void nmEnableTagging(); void nmRegisterTagID(int tag_id, char* name); void nmSetTag(void* ptr, int tag_id, void* tag); diff --git a/centrallix-lib/src/newmalloc.c b/centrallix-lib/src/newmalloc.c index ffa3daf80..c92b461be 100644 --- a/centrallix-lib/src/newmalloc.c +++ b/centrallix-lib/src/newmalloc.c @@ -40,6 +40,17 @@ #include "newmalloc.h" +/*** BUFFER_OVERFLOW_CHECKING adds 4 bytes of magic data to either end of + *** the memory buffer returned to the user by nmMalloc(). This allows us + *** to detect clobbered memory at the cost of increasing memory overhead + *** by 16 bytes per allocated buffer, and requires a full scan of the + *** allocated memory list twice in each nmMalloc() or nmFree() call. + *** + *** This check can also be run manually by calling nmCheckAll(). + *** + *** Note: nmCheckAll() is still defined if BUFFER_OVERFLOW_CHECKING is not + *** defined (it is a NOOP). + ***/ #ifdef BUFFER_OVERFLOW_CHECKING typedef struct _mem { @@ -59,7 +70,8 @@ typedef struct _mem pMemStruct startMemList; #endif -pOverlay lists[MAX_SIZE+1]; +/** List of overlay structs, used for caching allocated memory. **/ +pOverlay lists[MAX_SIZE+1]; /* TODO: Greg - Is this 65KB global variable a problem? (On the stack, it would be...) */ int listcnt[MAX_SIZE+1]; int outcnt[MAX_SIZE+1]; int outcnt_delta[MAX_SIZE+1]; @@ -92,6 +104,8 @@ typedef struct _RB pRegisteredBlockType blknames[MAX_SIZE+1]; + +/** Initialize the NewMalloc subsystem. **/ void nmInitialize() { @@ -116,16 +130,24 @@ nmInitialize() startMemList=NULL; #endif + /** Done. **/ is_init = true; } #ifdef BUFFER_OVERFLOW_CHECKING +/*** Check the before and after magic values on a MemStruct to detect memory + *** buffer overflows. + *** + *** @param mem A pointer to the memory struct to check. + *** @returns 0 on success, or -1 if an overflow is detected. + ***/ int nmCheckItem(pMemStruct mem) { int ret = 0; + /** Check the starting magic value. **/ if (mem->magic_start != MGK_MEMSTART) { fprintf(stderr, @@ -135,6 +157,7 @@ nmCheckItem(pMemStruct mem) ret = -1; } + /** Check the ending magic value. **/ if (ENDMAGIC(mem) != MGK_MEMEND) { fprintf(stderr, @@ -148,15 +171,20 @@ nmCheckItem(pMemStruct mem) } #endif +/*** Check the before and after magic values on all MemStructs to detect memory + *** buffer overflows. Causes a seg fault if such an overflow is detected. + ***/ void nmCheckAll() { #ifdef BUFFER_OVERFLOW_CHECKING int ret = 0; + /** Traverse the memory list and check each item. **/ for (pMemStruct mem = startMemList; mem != NULL; mem = mem->next) if (nmCheckItem(mem) == -1) ret = -1; + /** Handle error. **/ if (ret == -1) { printf("causing segfault to halt.......\n"); @@ -165,57 +193,94 @@ nmCheckAll() #endif } + #ifdef BUFFER_OVERFLOW_CHECKING +/*** Allocate new memory, using before and after magic values. + *** + *** @param size The size of the memory buffer to be allocated. + *** @returns A pointer to the start of the allocated memory buffer. + ***/ void* nmDebugMalloc(int size) { + /** Allocate space for the data. **/ pMemStruct tmp = (pMemStruct)malloc(size + EXTRA_MEM); if(tmp == NULL) return NULL; + /** Initialize data in the memory struct (including magic values). **/ tmp->size = size; tmp->magic_start = MGK_MEMSTART; ENDMAGIC(tmp) = MGK_MEMEND; + /** Prepend this mem struct to the MemList linked list. **/ tmp->next = startMemList; startMemList = tmp; + /** Return the memory data for the user to use. **/ return (void*)MEMDATA(tmp); } + +/*** Free a memory buffer allocated using `nmDebugMalloc()`. The before and + *** after magic values are checked and a warning is displayed if an overflow + *** has occurred (although this does not halt the program or function). + *** + *** @param ptr A pointer to the memory to be freed. + ***/ void nmDebugFree(void* ptr) { + /** Get the mem struct for the item being freed. **/ pMemStruct tmp = MEMDATATOSTRUCT(ptr); + /** Verify that our data hasn't been clobbered. **/ nmCheckItem(tmp); + /** Remove the item from the linked list. **/ if (tmp == startMemList) - { + { /* Item is at the start. */ startMemList = tmp->next; } else - { + { /* Item is not at the start. */ + /** Traverse the linked list to find the previous item. **/ pMemStruct prev = startMemList; while (prev->next != tmp) prev = prev->next; + /** Fix the gap that will be left by freeing this item. **/ prev->next = tmp->next; } + /** Free the item. **/ free(tmp); } -void* + +/*** Reallocates a memory block from `nmDebugMalloc()` (or `nmDebugRealloc()`) + *** to a new size, maintaining as much data as possible. Data loss only + *** occurs if the new size is smaller, in which case bits are lost starting + *** at the end of the buffer. + *** + *** @param ptr A pointer to the current buffer (deallocated by this call). + *** @param new_size The size that the buffer should be after this call. + *** @returns The new buffer, or NULL if an error occurs. + ***/ +void* nmDebugRealloc(void* ptr, int new_size) { + /** Behaves as nmDebugMalloc() if there is no target pointer. **/ if (ptr == NULL) return nmDebugMalloc(new_size); + /** Allocate new data. **/ void* new_ptr = (void*)nmDebugMalloc(new_size); if (new_ptr == NULL) return NULL; + /** Move the old data. **/ int old_size = MEMDATATOSTRUCT(ptr)->size; memmove(new_ptr, ptr, old_size); + /** Free the old allocation. **/ nmDebugFree(ptr); return new_ptr; @@ -234,11 +299,16 @@ nmSetErrFunction(int (*error_fn)()) } +/*** Clear the allocated memory block cache. This deallocates all memory + *** blocks that were marked as unused by a call to `nmFree()`, but were + *** moved to the cache instead of being freed to the OS memory pool. + ***/ void nmClear() { if (!is_init) nmInitialize(); + /** Iterate over each overlay list in the cache and clear it. **/ for (size_t size = MIN_SIZE; size <= MAX_SIZE; size++) { pOverlay ov = lists[size]; @@ -253,41 +323,60 @@ nmClear() } +/*** Allocate memory using block caching. The allocated block may be supplied + *** by the cache (if available), or requested from the operating system. + *** + *** @attention Should only be used for memory that will benefit from caching + *** (e.g. a struct of a constant size). Dynamically sized memory (such as + *** variable-length strings) should be allocated using nmSysMalloc() to + *** avoid overhead from unnecessary caching. + *** + *** @param size The size of the memory block to be allocated. + *** @returns A pointer to the start of the allocated memory block. + ***/ void* nmMalloc(int size) { void* tmp; if (!is_init) nmInitialize(); + /** Handle counting. **/ #ifdef GLOBAL_BLK_COUNTING nmMallocCnt++; #endif + /** Handle buffer overflow check. **/ #ifdef BUFFER_OVERFLOW_CHECKING nmCheckAll(); #endif + /** Use caching if the size can be cached. **/ if (MIN_SIZE <= size && size <= MAX_SIZE) { + /** Handle counting. **/ #ifdef SIZED_BLK_COUNTING outcnt[size]++; usagecnt[size]++; #endif + /** Cache check. **/ if (lists[size] == NULL) - { + { /* Miss. */ tmp = (void*)nmDebugMalloc(size); } else - { + { /* Hit. */ + /** Handle counting. **/ #ifdef GLOBAL_BLK_COUNTING nmMallocHits++; #endif + /** Pop allocated memory off of the start of the cache list. **/ tmp = lists[size]; ASSERTMAGIC(tmp, MGK_FREEMEM); lists[size] = lists[size]->Next; + /** Handle counting. **/ #ifdef SIZED_BLK_COUNTING listcnt[size]--; #endif @@ -295,14 +384,21 @@ nmMalloc(int size) } else { + /** Handle counting. **/ #ifdef GLOBAL_BLK_COUNTING - nmMallocTooBig++; + nmMallocTooBig++; /* TODO: Greg - Couldn't the memory also be too small? */ if (size > nmMallocLargest) nmMallocLargest = size; #endif + /** Caching isn't supported for this size: Allocate memory normally. **/ tmp = (void*)nmDebugMalloc(size); } + /** TODO: Greg - We might need more docs for overlays. **/ + /*** It seems like this code block is doing too many different things. It + *** uses overlays, which I don't fully understand, so I wasn't able to + *** simplify it. + ***/ if (tmp == NULL) { if (err_fn) err_fn("Insufficient system memory for operation."); @@ -313,11 +409,14 @@ nmMalloc(int size) OVERLAY(tmp)->Magic = MGK_ALLOCMEM; } + /** Handle overflow check. **/ #ifdef BUFFER_OVERFLOW_CHECKING nmCheckAll(); #endif + /** Handle memory leak checks. **/ #ifdef BLK_LEAK_CHECK + /** Find the next open index in the blocks array and record this block. **/ for (int i = 0; i < MAX_BLOCKS; i++) { if (blks[i] == NULL) @@ -329,29 +428,52 @@ nmMalloc(int size) } #endif + /** Return the allocated memory. **/ return tmp; } +/*** Free a memory buffer allocated using `nmMalloc()`. This buffer may be + *** deallocated into the operating system memory pool, or it may be cached + *** for reuse with `nmMalloc()`. + *** + *** @attention Be EXTREMELY careful not to provide an incorrect size value. + *** This can lead to memory blocks being cached incorrectly, which causes + *** errors to occur when they are reallocated, possibly FAR AWAY from the + *** original source of the bug. + *** + *** @param ptr A pointer to the memory to be freed. + *** @param size The size of the memory block to be freed. (Note: Even though + *** the OS does store this value, the C memory manager does not make it + *** available to us, so it must be provided for this function to run.) + ***/ void nmFree(void* ptr, int size) { if (!is_init) nmInitialize(); + /*** If there should be an overlay, assert that it does NOT indicate that + *** this memory was already freed and returned to the cache. + ***/ if (size >= MIN_SIZE) ASSERTNOTMAGIC(ptr, MGK_FREEMEM); + /** If the pointer is null, no work needed. **/ if (ptr == NULL) return; + /** Handle counting. **/ #ifdef GLOBAL_BLK_COUNTING nmFreeCnt++; #endif + /** Handle overflow check. **/ #ifdef BUFFER_OVERFLOW_CHECKING nmCheckAll(); #endif + /** Handle memory leak check. **/ #ifdef BLK_LEAK_CHECK + /** Find this block in the blocks array and remove it. **/ for (int i = 0; i < MAX_BLOCKS; i++) { if (blks[i] == ptr) @@ -363,10 +485,13 @@ nmFree(void* ptr, int size) } #endif + /** Check for the block cache if it is enabled. **/ #ifndef NO_BLK_CACHE if (size <= MAX_SIZE && size >= MIN_SIZE) { + /** Handle duplicate free check. **/ #ifdef DUP_FREE_CHECK + /** Search the freed memory cache to see if this memory is there. **/ for (pOverlay tmp = lists[size]; tmp != NULL; tmp = OVERLAY(tmp)->Next) { ASSERTMAGIC(OVERLAY(tmp),MGK_FREEMEM); @@ -379,11 +504,13 @@ nmFree(void* ptr, int size) } #endif + /** Add the freed memory to the cache. **/ OVERLAY(ptr)->Magic = MGK_FREEMEM; OVERLAY(ptr)->Next = lists[size]; lists[size] = OVERLAY(ptr); ptr = NULL; + /** Handle counting. **/ #ifdef SIZED_BLK_COUNTING outcnt[size]--; listcnt[size]++; @@ -391,18 +518,21 @@ nmFree(void* ptr, int size) } #endif + /** Free the block if it was not consumed by the cache. **/ if (ptr != NULL) { nmDebugFree(ptr); ptr = NULL; } + /** Handle overflow check. **/ #ifdef BUFFER_OVERFLOW_CHECKING nmCheckAll(); #endif } +/** Print stats about the NewMalloc subsystem, for debugging. **/ void nmStats() { @@ -420,33 +550,43 @@ nmStats() } +/** Register a new memory size with a name, for debugging. **/ void nmRegister(int size, char* name) { pRegisteredBlockType blk; + /** Ignore blocks too large to be cached. **/ if (size > MAX_SIZE) return; + /** Prepend a new RegisteredBlockType record to the list of records for this size. **/ blk = (pRegisteredBlockType)malloc(sizeof(RegisteredBlockType)); if (blk == NULL) return; blk->Next = blknames[size]; blknames[size] = blk; + /** Initialize values for this record. **/ blk->Magic = MGK_REGISBLK; blk->Size = size; strcpy(blk->Name, name); } + +/** Print debug information about the newmalloc system. **/ void nmDebug() { + /** Print the header for the block sizes table. **/ printf("size\tout\tcache\tusage\tnames\n"); + /** Iterate through each possible block size. **/ for (size_t size = MIN_SIZE; size < MAX_SIZE; size++) { + /** Skip unused block sizes. **/ if (usagecnt[size] == 0) continue; + /** Print stats about this block size. **/ printf("%ld\t%d\t%d\t%d\t", size, outcnt[size], listcnt[size], usagecnt[size]); pRegisteredBlockType blk = blknames[size]; @@ -460,29 +600,38 @@ nmDebug() printf("\n"); } + /** Print the header for the nmSysXYZ() info table. **/ printf("\n-----\n"); printf("size\toutcnt\n-------\t-------\n"); + /** Iterate through each possible block size. **/ for (size_t size = MIN_SIZE; size <= MAX_SIZE; size++) { + /** Skip unused block sizes. **/ if (nmsys_outcnt[size] == 0) continue; + /** Print the nmSysXYZ() block information. **/ printf("%ld\t%d\n", size, nmsys_outcnt[size]); } printf("\n"); } +/** Print debug information about the newmalloc system. **/ void nmDeltas() { + /** Print the header for the block size deltas table. **/ printf("size\tdelta\tnames\n-------\t-------\t-------\n"); + /** Iterate through each possible block size. **/ int total_delta = 0; for (size_t size = MIN_SIZE; size <= MAX_SIZE; size++) { + /** Skip entries where there is no change. **/ if (outcnt[size] == outcnt_delta[size]) continue; + /** Print the change and add it to the total_delta. **/ printf("%ld\t%d\t", size, outcnt[size] - outcnt_delta[size]); total_delta += (size * (outcnt[size] - outcnt_delta[size])); @@ -494,11 +643,14 @@ nmDeltas() blk = blk->Next; } + /** End of line. **/ printf("\n"); + /** Reset the delta. **/ outcnt_delta[size] = outcnt[size]; } + /** Print the header for the nmSysXYZ() info table. **/ printf("\nsize\tdelta\n-------\t-------\n"); for (size_t size = MIN_SIZE; size <= MAX_SIZE; size++) { @@ -510,86 +662,145 @@ nmDeltas() } printf("\n"); + /** Print the total delta. **/ + /** TODO: Israel - Change this to use snprint_bytes() once that function is available. **/ printf("delta %d total bytes\n", total_delta); } +/*** Allocate memory without using block caching. The size of the allocated + *** memory is stored at the start of the memory block for debugging. + *** + *** @attention Should be used for memory that will NOT benefit from caching + *** (e.g. a variable length string). Consistently sized memory (such as + *** a struct of a constant size) should be allocated using nmMalloc() to + *** improve performance. + *** + *** @param size The size of the memory block to be allocated. + *** @returns A pointer to the start of the allocated memory block. + ***/ void* nmSysMalloc(int size) { + /** Fallback if sysMalloc() is disabled. **/ #ifndef NM_USE_SYSMALLOC return (void*)nmDebugMalloc(size); #else + /** Allocate the requested space, plus the initial size int. **/ char* ptr = (char*)nmDebugMalloc(sizeof(int) + size); if (ptr == NULL) return NULL; + /** Set the size int. **/ *(int*)ptr = size; + /** Update sized block counting, if necessary. **/ #ifdef SIZED_BLK_COUNTING if (size > 0 && size <= MAX_SIZE) nmsys_outcnt[size]++; #endif + /** Return the allocated memory (starting after the size int). **/ return (void*)(sizeof(int) + ptr); #endif } +/*** Free a memory buffer allocated using `nmSysMalloc()` (or similar). + *** + *** @param ptr A pointer to the memory to be freed. + ***/ void nmSysFree(void* ptr) { + /** Fallback if sysMalloc() is disabled. **/ #ifndef NM_USE_SYSMALLOC nmDebugFree(ptr); #else + /** Count sized blocks, if enabled. **/ #ifdef SIZED_BLK_COUNTING int size; size = *(int*)(((char*)ptr)-sizeof(int)); if (size > 0 && size <= MAX_SIZE) nmsys_outcnt[size]--; #endif + /** Free the initial size int, as well as the rest of the allocated memory. **/ nmDebugFree(((char*)ptr) - sizeof(int)); #endif return; } +/*** Reallocates a memory block from `nmSysMalloc()` (or similar) to a new + *** size, maintaining as much data as possible. Data loss only occurs if the + *** new size is smaller, in which case bits are lost starting at the end of + *** the buffer. + *** + *** @param ptr A pointer to the current buffer (deallocated by this call). + *** @param new_size The size that the buffer should be after this call. + *** @returns The new buffer, or NULL if an error occurs. + ***/ void* nmSysRealloc(void* ptr, int new_size) { + /** Fallback if sysMalloc() is disabled. **/ #ifndef NM_USE_SYSMALLOC return (void*)nmDebugRealloc(ptr, new_size); #else + /** Behaves as nmSysMalloc() if there is no target pointer. **/ if (ptr == NULL) return nmSysMalloc(new_size); + /** Realloc the given memory, taking the initial size int into account into account. **/ char* newptr = (char*)nmDebugRealloc((((char*)ptr) - sizeof(int)), sizeof(int) + new_size); if (newptr == NULL) return NULL; + /** Update the initial size int. **/ *(int*)newptr = new_size; + /** Handle counting. **/ #ifdef SIZED_BLK_COUNTING int size = *(int*)(((char*)ptr)-sizeof(int)); if (0 < size && size <= MAX_SIZE) nmsys_outcnt[size]--; if (0 < new_size && new_size <= MAX_SIZE) nmsys_outcnt[new_size]++; #endif + /** Return the pointer to the new memory. **/ return (void*)(sizeof(int) + newptr); #endif } +/*** Duplicate a string into a new memory buffer, which is allocated by using + *** `nmSysMalloc()` (and thus, it should be freed with `nmSysFree()` to avoid + *** causing a memory leak). + *** + *** Note: The string is not deallocated by this function call. Thus, it can + *** be stack allocated, heap allocated, or even a string literal without + *** causing an error. + *** + *** @attention The str pointer is _assumed_ to point to a null-terminated + *** string. If this is not the case, the behavior is undefined, as with + *** the C standard `strdup()` function. + *** + *** @param str The string to be duplicated. + *** @returns A pointer to the new string buffer containing the string, or + *** NULL if an error occurs. + ***/ char* nmSysStrdup(const char* str) { + /** Fallback if sysMalloc() is disabled. **/ #ifndef NM_USE_SYSMALLOC return strdup(str); #else - size_t n = strlen(str) + 1u; + /** Allocate space for the string. **/ + size_t n = strlen(str) + 1u; /* Length, including the null terminator. */ char* new_str = (char*)nmSysMalloc(n); if (new_str == NULL) return NULL; + /** Copy the string into the new memory. **/ memcpy(new_str, str, n); return new_str; From 23f3f539fb1b6319ef410b1d7ae9a91fecab6bb3 Mon Sep 17 00:00:00 2001 From: Lightning11wins Date: Wed, 3 Dec 2025 17:28:27 -0700 Subject: [PATCH 3/3] Add a warning when using nmStats() with the necessary stat tracking disabled. Abstract registered block name printing into a public helper function. Optimize nmSysRealloc() to do nothing when asked to reallocate memory to the current size. --- centrallix-lib/include/newmalloc.h | 1 + centrallix-lib/src/newmalloc.c | 54 +++++++++++++++++++----------- 2 files changed, 36 insertions(+), 19 deletions(-) diff --git a/centrallix-lib/include/newmalloc.h b/centrallix-lib/include/newmalloc.h index 60b2d8a2e..3fb752587 100644 --- a/centrallix-lib/include/newmalloc.h +++ b/centrallix-lib/include/newmalloc.h @@ -72,6 +72,7 @@ void* nmMalloc(int size); void nmFree(void* ptr, int size); void nmStats(); void nmRegister(int size, char* name); +void nmPrintNames(int size); void nmDebug(); void nmDeltas(); void* nmSysMalloc(int size); diff --git a/centrallix-lib/src/newmalloc.c b/centrallix-lib/src/newmalloc.c index c92b461be..dd0684ac7 100644 --- a/centrallix-lib/src/newmalloc.c +++ b/centrallix-lib/src/newmalloc.c @@ -538,6 +538,12 @@ nmStats() { if (!is_init) nmInitialize(); + /** Warn if statistics are not being tracked. **/ + #ifndef GLOBAL_BLK_COUNTING + printf("Warning: GLOBAL_BLK_COUNTING is disabled.\n"); + #endif + + /** Print subsystem stats. **/ printf( "NewMalloc subsystem statistics:\n" " nmMalloc: %d calls, %d hits (%3.3f%%)\n" @@ -571,6 +577,22 @@ nmRegister(int size, char* name) strcpy(blk->Name, name); } +/*** Print the registered names for a block of data of a given size to stdout. + *** + *** @param size The size of block to query. + ***/ +void +nmPrintNames(int size) + { + /*** Traverse the linked list that holds all registered names for the given + *** size and print each one. + **/ + for (pRegisteredBlockType blk = blknames[size]; blk != NULL; blk = blk->Next) + { + ASSERTMAGIC(blk, MGK_REGISBLK); + printf("%s ", blk->Name); + } + } /** Print debug information about the newmalloc system. **/ @@ -589,13 +611,8 @@ nmDebug() /** Print stats about this block size. **/ printf("%ld\t%d\t%d\t%d\t", size, outcnt[size], listcnt[size], usagecnt[size]); - pRegisteredBlockType blk = blknames[size]; - while(blk) - { - ASSERTMAGIC(blk,MGK_REGISBLK); - printf("%s ", blk->Name); - blk = blk->Next; - } + /** Print each name for this block size. **/ + nmPrintNames(size); printf("\n"); } @@ -635,13 +652,8 @@ nmDeltas() printf("%ld\t%d\t", size, outcnt[size] - outcnt_delta[size]); total_delta += (size * (outcnt[size] - outcnt_delta[size])); - pRegisteredBlockType blk = blknames[size]; - while(blk) - { - ASSERTMAGIC(blk,MGK_REGISBLK); - printf("%s ", blk->Name); - blk = blk->Next; - } + /** Print each name for this block size from the linked list. **/ + nmPrintNames(size); /** End of line. **/ printf("\n"); @@ -751,22 +763,26 @@ nmSysRealloc(void* ptr, int new_size) /** Behaves as nmSysMalloc() if there is no target pointer. **/ if (ptr == NULL) return nmSysMalloc(new_size); + /** If no work needs to be done, do nothing. **/ + void* buffer_ptr = ((char*)ptr) - sizeof(int); + const int size = *(int*)buffer_ptr; + if (size == new_size) return ptr; + /** Realloc the given memory, taking the initial size int into account into account. **/ - char* newptr = (char*)nmDebugRealloc((((char*)ptr) - sizeof(int)), sizeof(int) + new_size); - if (newptr == NULL) return NULL; + char* new_ptr = (char*)nmDebugRealloc(buffer_ptr, sizeof(int) + new_size); + if (new_ptr == NULL) return NULL; /** Update the initial size int. **/ - *(int*)newptr = new_size; + *(int*)new_ptr = new_size; /** Handle counting. **/ #ifdef SIZED_BLK_COUNTING - int size = *(int*)(((char*)ptr)-sizeof(int)); if (0 < size && size <= MAX_SIZE) nmsys_outcnt[size]--; if (0 < new_size && new_size <= MAX_SIZE) nmsys_outcnt[new_size]++; #endif /** Return the pointer to the new memory. **/ - return (void*)(sizeof(int) + newptr); + return (void*)(sizeof(int) + new_ptr); #endif }