summaryrefslogtreecommitdiffstats
path: root/src/kvilib/core/kvi_malloc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/kvilib/core/kvi_malloc.cpp')
-rw-r--r--src/kvilib/core/kvi_malloc.cpp198
1 files changed, 198 insertions, 0 deletions
diff --git a/src/kvilib/core/kvi_malloc.cpp b/src/kvilib/core/kvi_malloc.cpp
new file mode 100644
index 00000000..9c418ec5
--- /dev/null
+++ b/src/kvilib/core/kvi_malloc.cpp
@@ -0,0 +1,198 @@
+//=============================================================================
+//
+// File : kvi_malloc.cpp
+// Creation date : Sun Jun 18 2000 18:26:27 CEST by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 1999-2006 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program is FREE software. You can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your opinion) any later version.
+//
+// This program is distributed in the HOPE that it will be USEFUL,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, write to the Free Software Foundation,
+// Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+//=============================================================================
+
+//=============================================================================
+// C memory allocation routines
+// This stuff is rather unused, because in normal compilations
+// kvi_malloc , kvi_free and kvi_realloc are macros (see kvi_malloc.h)
+//=============================================================================
+
+#define __KVILIB__
+
+#define _KVI_MALLOC_CPP_
+#include "kvi_malloc.h"
+
+#include <stdio.h>
+
+
+
+#ifdef COMPILE_MEMORY_PROFILE
+
+ //
+ // Memory profile stuff
+ // Used to find memory leaks etc...
+ //
+
+ #include "kvi_pointerlist.h"
+
+ typedef struct _KviMallocEntry {
+ struct _KviMallocEntry * prev;
+ void * pointer;
+ int size;
+ void * return_addr1;
+ void * return_addr2;
+ struct _KviMallocEntry * next;
+ } KviMallocEntry;
+
+ int g_iMaxRequestSize = 0;
+ void * g_pMaxRequestReturnAddress1 = 0;
+ void * g_pMaxRequestReturnAddress2 = 0;
+ unsigned int g_iMallocCalls = 0;
+ unsigned int g_iReallocCalls = 0;
+ unsigned int g_iFreeCalls = 0;
+ unsigned int g_iTotalMemAllocated = 0;
+ unsigned int g_uAllocationPeak = 0;
+ KviMallocEntry * g_pEntries = 0;
+
+ void * kvi_malloc(int size)
+ {
+ g_iMallocCalls ++;
+ g_iTotalMemAllocated += size;
+ if(g_iTotalMemAllocated > g_uAllocationPeak)g_uAllocationPeak = g_iTotalMemAllocated;
+ if(g_iMaxRequestSize < size){
+ g_iMaxRequestSize = size;
+ g_pMaxRequestReturnAddress1 = __builtin_return_address(1);
+ g_pMaxRequestReturnAddress2 = __builtin_return_address(2);
+ }
+ KviMallocEntry * e = (KviMallocEntry *)malloc(sizeof(KviMallocEntry));
+ e->pointer = malloc(size);
+ e->size = size;
+ e->return_addr1 = __builtin_return_address(1);
+ e->return_addr2 = __builtin_return_address(2);
+ e->next = g_pEntries;
+ e->prev = 0;
+ if(g_pEntries)g_pEntries->prev = e;
+ g_pEntries = e;
+ return e->pointer;
+ }
+
+ void * kvi_realloc(void * ptr,int size)
+ {
+ g_iReallocCalls ++;
+ if(ptr == 0)return kvi_malloc(size);
+ if(g_iMaxRequestSize < size){
+ g_iMaxRequestSize = size;
+ g_pMaxRequestReturnAddress1 = __builtin_return_address(1);
+ g_pMaxRequestReturnAddress2 = __builtin_return_address(2);
+ }
+ KviMallocEntry *e = g_pEntries;
+ while(e){
+ if(e->pointer == ptr){
+ g_iTotalMemAllocated -= e->size;
+ g_iTotalMemAllocated += size;
+ if(g_iTotalMemAllocated > g_uAllocationPeak)g_uAllocationPeak = g_iTotalMemAllocated;
+ e->pointer = realloc(ptr,size);
+ e->size = size;
+ e->return_addr1 = __builtin_return_address(1);
+ e->return_addr2 = __builtin_return_address(2);
+ return e->pointer;
+ }
+ e = e->next;
+ }
+ fprintf(stderr,"Attempt to realloc an inexisting pointer (%p) (called from %p (%p))\n",ptr,__builtin_return_address(1),__builtin_return_address(2));
+ return realloc(ptr,size);
+ }
+
+ void kvi_free(void * ptr)
+ {
+ g_iFreeCalls++;
+ if(ptr == 0){
+ fprintf(stderr,"Attempt to free a null pointer (called from %p (%p))\n",__builtin_return_address(1),__builtin_return_address(2));
+ exit(-1);
+ }
+ KviMallocEntry * e= g_pEntries;
+ while(e){
+ if(e->pointer == ptr){
+ g_iTotalMemAllocated -= e->size;
+ if(e->prev){
+ if(e == g_pEntries)fprintf(stderr,"Mem profiling internal error!\n");
+ e->prev->next = e->next;
+ if(e->next)e->next->prev = e->prev;
+ } else {
+ if(e != g_pEntries)fprintf(stderr,"Mem profiling internal error!\n");
+ if(e->next)e->next->prev = 0;
+ g_pEntries = e->next;
+ }
+ free(e);
+ return;
+ }
+ e = e->next;
+ }
+ fprintf(stderr,"Attempt to free an inexisting pointer (%p) (called from %p (%p))\n",ptr,__builtin_return_address(1),__builtin_return_address(2));
+ }
+
+ void kvi_memory_profile() __attribute__((destructor));
+ void kvi_memory_profile()
+ {
+ unsigned int countUnfreed = 0;
+ KviMallocEntry * e = g_pEntries;
+ while(e){
+ countUnfreed++;
+ e = e->next;
+ }
+ fprintf(stderr,"|====|====|====|====|====|====|====|====\n");
+ fprintf(stderr,"| Memory profile for KVIrc\n");
+ fprintf(stderr,"| Unfreed chunks : %d\n",countUnfreed);
+ fprintf(stderr,"| Total unfreed memory : %u bytes\n",g_iTotalMemAllocated);
+ fprintf(stderr,"|====|====|====|====|====|====|====|====\n");
+ fprintf(stderr,"| Possible unfreed chunks dump:\n");
+ e = g_pEntries;
+ while(e){
+ fprintf(stderr,"|====|====|\n");
+ fprintf(stderr,"| Currently unfreed chunk: %p\n",e->pointer);
+ fprintf(stderr,"| Size: %d\n",e->size);
+ fprintf(stderr,"| Caller address 1: %p\n",e->return_addr1);
+ fprintf(stderr,"| Caller address 2: %p\n",e->return_addr2);
+ if(e->size > 10)fprintf(stderr,"| Data: %.10s\n",e->pointer);
+ else if(e->size > 5)fprintf(stderr,"| Data: %.5s\n",e->pointer);
+ KviMallocEntry *toFree = e;
+ e = e->next;
+ free(toFree);
+ }
+ fprintf(stderr,"|====|====|====|====|====|====|====|====\n");
+ fprintf(stderr,"| Allocation peak : %u bytes\n",g_uAllocationPeak);
+ fprintf(stderr,"|====|====|====|====|====|====|====|====\n");
+ fprintf(stderr,"| Max request size : %d bytes\n",g_iMaxRequestSize);
+ fprintf(stderr,"| Called from %p (%p)\n",g_pMaxRequestReturnAddress1,g_pMaxRequestReturnAddress2);
+ fprintf(stderr,"|====|====|====|====|====|====|====|====\n");
+ fprintf(stderr,"| Malloc calls: %u\n",g_iMallocCalls);
+ fprintf(stderr,"| Realloc calls: %u\n",g_iReallocCalls);
+ fprintf(stderr,"| Free calls: %u\n",g_iFreeCalls);
+ fprintf(stderr,"|====|====|====|====|====|====|====|====\n");
+ }
+
+#else
+
+ #ifdef COMPILE_MEMORY_CHECKS
+
+ void outOfMemory()
+ {
+ //What a cool message :)
+ fprintf(stderr,"Virtual memory exhausted in malloc call....bye!\n");
+ exit(-1);
+ }
+
+ #endif
+
+#endif