1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
inline void *nzalloc(uint_32 size, char *name) //Allocates memory, NULL on failure (ran out of memory), protected malloc!
{
if (!size) return NULL; //Can't allocate nothing!
void *ptr = NULL;
int times=10; //Try 10 times till giving up!
for (;(!ptr && times);) //Try for some times!
{
ptr = malloc(size); //Try to allocate!
--times; //Next try!
}
if (ptr!=NULL) //Allocated and a valid size?
{
if (registerptr(ptr,size,name,&zalloc_free)) //Register the pointer with the detection system!
{
if (allow_zallocfaillog && DEBUG_ALLOCDEALLOC) dolog("zalloc","Memory has been allocated. Size: %i. Free memory: %i, name: %s",size,freemem(),name); //Log our allocated memory!
return ptr; //Give the original pointer, cleared to 0!
}
if (allow_zallocfaillog && DEBUG_ALLOCDEALLOC) dolog("zalloc","Ran out of registrations while allocating %i bytes of data for block %s.",size,name);
free(ptr); //Free it, can't generate any more!
}
else if (allow_zallocfaillog)
{
if (freemem()>=size) //Enough memory after all?
{
dolog("zalloc","Error while allocating %i bytes of data for block \"%s\" with enough free memory(%i bytes).",size,name,freemem());
}
else
{
dolog("zalloc","Ran out of memory while allocating %i bytes of data for block \"%s\".",size,name);
}
logpointers(); //Log a dump of pointers!
}
return NULL; //Not allocated!
}
inline void *zalloc(uint_32 size, char *name) //Same as nzalloc, but clears the allocated memory!
{
void *ptr;
ptr = nzalloc(size,name); //Try to allocate!
if (ptr) //Allocated?
{
return memset(ptr,0,size); //Give the original pointer, cleared to 0!
}
return NULL; //Not allocated!
}
inline void freez(void **ptr, uint_32 size, char *name)
{
if (!ptr) return; //Invalid pointer to deref!
int ptrn=-1;
if ((ptrn = matchptr(*ptr,0,size))>-1) //Found fully existant?
{
if (allow_zallocfaillog && DEBUG_ALLOCDEALLOC) dolog("zalloc","Freeing pointer %s with size %i bytes...",registeredpointers[ptrn].name,size); //Show we're freeing this!
if (!registeredpointers[ptrn].dealloc) //Deallocation not registered?
{
return; //We can't be freed using this function! We're still allocated!
}
registeredpointers[ptrn].dealloc(ptr,size); //Release the memory tied to it using the registered deallocation function, if any!
}
else if (allow_zallocfaillog && DEBUG_ALLOCDEALLOC && ptr!=NULL) //An pointer pointing to nothing?
{
dolog("zalloc","Warning: freeing pointer which isn't an allocated reference: %s",name); //Log it!
}
//Still allocated, we might be a pointer which is a subset, so we can't deallocate!
}
inline void unregisterptrall() //Free all allocated memory still allocated (on shutdown only, garbage collector)!
{
int i;
for (i=0;i<NUMITEMS(registeredpointers);i++)
{
void *ptr;
ptr = registeredpointers[i].pointer; //A pointer!
freez(&ptr,registeredpointers[i].size,"Unregisterptrall"); //Unregister a pointer!
}
}
inline void freezall() //Same as unregisterptrall
{
unregisterptrall(); //Unregister all!
}
inline void *memprotect(void *ptr, uint_32 size) //Checks address of pointer!
{
if (matchptr(ptr,0,size)) //Pointer matched?
{
return ptr; //Give the pointer!
}
return NULL; //Invalid!
}
inline uint_32 freemem() //Free memory left! We work!
{
//dolog("zalloc","Detecting free memory...");
uint_32 curalloc; //Current allocated memory!
char *buffer;
uint_32 multiplier; //The multiplier!
curalloc = 0; //Reset at 1 bytes!
multiplier = 100000000; //Start at max multiplier (100MB)!
byte times = 9; //Times!
times = 9; //Times 9 to start with!
uint_32 lastzalloc = 0;
allow_zallocfaillog = 0; //Don't allow!
byte allocated = 0; //Allocated?
while (1) //While not done...
{
lastzalloc = (curalloc+(multiplier*times)); //Last zalloc!
allocated = 0; //Default: not allocated!
buffer = (char *)zalloc(lastzalloc,"freememdetect"); //Try allocating, don't have to be cleared!
if (buffer) //Allocated?
{
freez((void **)&buffer,lastzalloc,"Freemem@Cleanup"); //Release memory for next try!
buffer = NULL; //Not allocated anymore!
curalloc = lastzalloc; //Set detected memory!
//dolog("zalloc","Free memory step: %i",curalloc); //Show our step! WE WORK!
allocated = 1; //We're allocated!
}
if (!times || allocated) //Either nothing left or allocated?
{
multiplier /= 10; //Next digit!
times = 9; //Reset times for next try!
}
else //Calculate next digit!
{
--times; //Next digit!
}
if (!multiplier) //Gotten an allocation and/or done?
{
break; //Stop searching: we're done!
}
//We're to continue!
} //We have success!
if (buffer) //Still allocated?
{
freez((void **)&buffer,lastzalloc,"Freemem@FinalCleanup"); //Still allocated=>release?
}
//dolog("zalloc","Free memory detected: %i bytes",curalloc);
allow_zallocfaillog = 1; //Allow again!
return curalloc; //Give free allocatable memory size!
}
|