root/src/common/malloc.c @ 13

Revision 1, 19.7 kB (checked in by jinshiro, 17 years ago)
Line 
1// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
2// For more information, see LICENCE in the main folder
3
4#include "../common/malloc.h"
5#include "../common/core.h"
6#include "../common/showmsg.h"
7
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <time.h>
12
13// no logging for minicore
14#if defined(MINICORE) && defined(LOG_MEMMGR)
15#undef LOG_MEMMGR
16#endif
17
18void* aMalloc_(size_t size, const char *file, int line, const char *func)
19{
20        void *ret = MALLOC(size, file, line, func);
21        // ShowMessage("%s:%d: in func %s: aMalloc %d\n",file,line,func,size);
22        if (ret == NULL){
23                ShowFatalError("%s:%d: in func %s: aMalloc error out of memory!\n",file,line,func);
24                exit(EXIT_FAILURE);
25        }
26
27        return ret;
28}
29void* aMallocA_(size_t size, const char *file, int line, const char *func)
30{
31        void *ret = MALLOCA(size, file, line, func);
32        // ShowMessage("%s:%d: in func %s: aMallocA %d\n",file,line,func,size);
33        if (ret == NULL){
34                ShowFatalError("%s:%d: in func %s: aMallocA error out of memory!\n",file,line,func);
35                exit(EXIT_FAILURE);
36        }
37
38        return ret;
39}
40void* aCalloc_(size_t num, size_t size, const char *file, int line, const char *func)
41{
42        void *ret = CALLOC(num, size, file, line, func);
43        // ShowMessage("%s:%d: in func %s: aCalloc %d %d\n",file,line,func,num,size);
44        if (ret == NULL){
45                ShowFatalError("%s:%d: in func %s: aCalloc error out of memory!\n", file, line, func);
46                exit(EXIT_FAILURE);
47        }
48        return ret;
49}
50void* aCallocA_(size_t num, size_t size, const char *file, int line, const char *func)
51{
52        void *ret = CALLOCA(num, size, file, line, func);
53        // ShowMessage("%s:%d: in func %s: aCallocA %d %d\n",file,line,func,num,size);
54        if (ret == NULL){
55                ShowFatalError("%s:%d: in func %s: aCallocA error out of memory!\n",file,line,func);
56                exit(EXIT_FAILURE);
57        }
58        return ret;
59}
60void* aRealloc_(void *p, size_t size, const char *file, int line, const char *func)
61{
62        void *ret = REALLOC(p, size, file, line, func);
63        // ShowMessage("%s:%d: in func %s: aRealloc %p %d\n",file,line,func,p,size);
64        if (ret == NULL){
65                ShowFatalError("%s:%d: in func %s: aRealloc error out of memory!\n",file,line,func);
66                exit(EXIT_FAILURE);
67        }
68        return ret;
69}
70char* aStrdup_(const char *p, const char *file, int line, const char *func)
71{
72        char *ret = STRDUP(p, file, line, func);
73        // ShowMessage("%s:%d: in func %s: aStrdup %p\n",file,line,func,p);
74        if (ret == NULL){
75                ShowFatalError("%s:%d: in func %s: aStrdup error out of memory!\n", file, line, func);
76                exit(EXIT_FAILURE);
77        }
78        return ret;
79}
80void aFree_(void *p, const char *file, int line, const char *func)
81{
82        // ShowMessage("%s:%d: in func %s: aFree %p\n",file,line,func,p);
83        if (p)
84                FREE(p, file, line, func);
85
86        p = NULL;
87}
88
89#ifdef GCOLLECT
90
91void* _bcallocA(size_t size, size_t cnt)
92{
93        void *ret = MALLOCA(size * cnt);
94        if (ret) memset(ret, 0, size * cnt);
95        return ret;
96}
97void* _bcalloc(size_t size, size_t cnt)
98{
99        void *ret = MALLOC(size * cnt);
100        if (ret) memset(ret, 0, size * cnt);
101        return ret;
102}
103char* _bstrdup(const char *chr)
104{
105        int len = strlen(chr);
106        char *ret = (char*)MALLOC(len + 1);
107        if (ret) memcpy(ret, chr, len + 1);
108        return ret;
109}
110
111#endif
112
113#ifdef USE_MEMMGR
114
115#if defined(DEBUG)
116#define DEBUG_MEMMGR
117#endif
118
119/* USE_MEMMGR */
120
121/*
122 * ƒƒ‚ƒŠƒ}ƒl[ƒWƒƒ
123 *     malloc , free ‚̏ˆ—‚ðŒø—Š“I‚ɏo—ˆ‚邿‚€‚É‚µ‚œ‚à‚́B
124 *     •¡ŽG‚ȏˆ—‚ðs‚Á‚Ä‚¢‚é‚̂ŁAŽáбd‚­‚Ȃ邩‚à‚µ‚ê‚Ü‚¹‚ñB
125 *
126 * ƒf[ƒ^\‘¢‚Ȃǁià–Ÿ‰ºŽè‚Å‚·‚¢‚Ü‚¹‚ñ^^; j
127 *     Eƒƒ‚ƒŠ‚𕡐”‚́uƒuƒƒbƒNv‚É•ª‚¯‚āA‚³‚ç‚ɃuƒƒbƒN‚𕡐”‚́uƒ†ƒjƒbƒgv
128 *       ‚É•ª‚¯‚Ä‚¢‚Ü‚·Bƒ†ƒjƒbƒg‚̃TƒCƒY‚́A‚PƒuƒƒbƒN‚Ì—e—ʂ𕡐”ŒÂ‚ɋϓ™”z•ª
129 *       ‚µ‚œ‚à‚̂ł·B‚œ‚Æ‚Š‚ÎA‚Pƒ†ƒjƒbƒg32KB‚̏ꍇAƒuƒƒbƒN‚P‚‚Í32Byte‚̃†
130 *       ƒjƒbƒg‚ªA1024ŒÂW‚Ü‚Á‚ďo—ˆ‚Ä‚¢‚œ‚èA64Byte‚̃†ƒjƒbƒg‚ª 512ŒÂW‚Ü‚Á‚Ä
131 *       o—ˆ‚Ä‚¢‚œ‚肵‚Ü‚·Bipadding,unit_head ‚ðœ‚­j
132 *
133 *     EƒuƒƒbƒN“¯Žm‚ÍƒŠƒ“ƒNƒŠƒXƒg(block_prev,block_next) ‚ł‚Ȃª‚èA“¯‚¶ƒTƒC
134 *       ƒY‚ðŽ‚ÂƒuƒƒbƒN“¯Žm‚àƒŠƒ“ƒNƒŠƒXƒg(hash_prev,hash_nect) ‚ł‚È
135 *       ‚ª‚Á‚Ä‚¢‚Ü‚·B‚»‚ê‚É‚æ‚èA•s—v‚ƂȂÁ‚œƒƒ‚ƒŠ‚̍ė˜—p‚ªŒø—Š“I‚ɍs‚Ђ܂·B
136 */
137
138/* ƒuƒƒbƒN‚̃Aƒ‰ƒCƒƒ“ƒg */
139#define BLOCK_ALIGNMENT1        16
140#define BLOCK_ALIGNMENT2        64
141
142/* ƒuƒƒbƒN‚É“ü‚éƒf[ƒ^—Ê */
143#define BLOCK_DATA_COUNT1       128
144#define BLOCK_DATA_COUNT2       608
145
146/* ƒuƒƒbƒN‚̑傫‚³: 16*128 + 64*576 = 40KB */
147#define BLOCK_DATA_SIZE1        ( BLOCK_ALIGNMENT1 * BLOCK_DATA_COUNT1 )
148#define BLOCK_DATA_SIZE2        ( BLOCK_ALIGNMENT2 * BLOCK_DATA_COUNT2 )
149#define BLOCK_DATA_SIZE         ( BLOCK_DATA_SIZE1 + BLOCK_DATA_SIZE2 )
150
151/* ˆê“x‚ÉŠm•Û‚·‚éƒuƒƒbƒN‚̐”B */
152#define BLOCK_ALLOC             104
153
154/* ƒuƒƒbƒN */
155struct block {
156        struct block* block_next;               /* ŽŸ‚ÉŠm•Û‚µ‚œ—̈æ */
157        struct block* unfill_prev;              /* ŽŸ‚Ì–„‚Ü‚Á‚Ä‚¢‚È‚¢—̈æ */
158        struct block* unfill_next;              /* ŽŸ‚Ì–„‚Ü‚Á‚Ä‚¢‚È‚¢—̈æ */
159        unsigned short unit_size;               /* ƒ†ƒjƒbƒg‚̑傫‚³ */
160        unsigned short unit_hash;               /* ƒ†ƒjƒbƒg‚̃nƒbƒVƒ… */
161        unsigned short unit_count;              /* ƒ†ƒjƒbƒg‚̌” */
162        unsigned short unit_used;               /* Žg—pƒ†ƒjƒbƒg” */
163        unsigned short unit_unfill;             /* –¢Žg—pƒ†ƒjƒbƒg‚̏ꏊ */
164        unsigned short unit_maxused;    /* Žg—pƒ†ƒjƒbƒg‚̍őå’l */
165        char   data[ BLOCK_DATA_SIZE ];
166};
167
168struct unit_head {
169        struct block   *block;
170        const  char*   file;
171        unsigned short line;
172        unsigned short size;
173        long           checksum;
174};
175
176static struct block* hash_unfill[BLOCK_DATA_COUNT1 + BLOCK_DATA_COUNT2 + 1];
177static struct block* block_first, *block_last, block_head;
178
179/* ƒƒ‚ƒŠ‚ðŽg‚¢‰ñ‚¹‚È‚¢—̈æ—p‚̃f[ƒ^ */
180struct unit_head_large {
181        size_t                  size;
182        struct unit_head_large* prev;
183        struct unit_head_large* next;
184        struct unit_head        unit_head;
185};
186
187static struct unit_head_large *unit_head_large_first = NULL;
188
189static struct block* block_malloc(unsigned short hash);
190static void          block_free(struct block* p);
191static size_t        memmgr_usage_bytes;
192
193#define block2unit(p, n) ((struct unit_head*)(&(p)->data[ p->unit_size * (n) ]))
194#define memmgr_assert(v) do { if(!(v)) { ShowError("Memory manager: assertion '" #v "' failed!\n"); } } while(0)
195
196static unsigned short size2hash( size_t size )
197{
198        if( size <= BLOCK_DATA_SIZE1 ) {
199                return (unsigned short)(size + BLOCK_ALIGNMENT1 - 1) / BLOCK_ALIGNMENT1;
200        } else if( size <= BLOCK_DATA_SIZE ){
201                return (unsigned short)(size - BLOCK_DATA_SIZE1 + BLOCK_ALIGNMENT2 - 1) / BLOCK_ALIGNMENT2
202                                + BLOCK_DATA_COUNT1;
203        } else {
204                return 0xffff;  // ƒuƒƒbƒN’·‚ð’Ž‚Š‚éê‡‚Í hash ‚É‚µ‚È‚¢
205        }
206}
207
208static size_t hash2size( unsigned short hash )
209{
210        if( hash <= BLOCK_DATA_COUNT1) {
211                return hash * BLOCK_ALIGNMENT1;
212        } else {
213                return (hash - BLOCK_DATA_COUNT1) * BLOCK_ALIGNMENT2 + BLOCK_DATA_SIZE1;
214        }
215}
216
217void* _mmalloc(size_t size, const char *file, int line, const char *func )
218{
219        struct block *block;
220        short size_hash = size2hash( size );
221        struct unit_head *head;
222
223        if (((long) size) < 0) {
224                ShowError("_mmalloc: %d\n", size);
225                return 0;
226        }
227       
228        if(size == 0) {
229                return NULL;
230        }
231        memmgr_usage_bytes += size;
232
233        /* ƒuƒƒbƒN’·‚ð’Ž‚Š‚é—̈æ‚ÌŠm•ۂɂ́Amalloc() ‚ð—p‚¢‚é */
234        /* ‚»‚̍ہAunit_head.block ‚É NULL ‚ð‘ã“ü‚µ‚Ä‹æ•Ê‚·‚é */
235        if(hash2size(size_hash) > BLOCK_DATA_SIZE - sizeof(struct unit_head)) {
236                struct unit_head_large* p = (struct unit_head_large*)MALLOC(sizeof(struct unit_head_large)+size,file,line,func);
237                if(p != NULL) {
238                        p->size            = size;
239                        p->unit_head.block = NULL;
240                        p->unit_head.size  = 0;
241                        p->unit_head.file  = file;
242                        p->unit_head.line  = line;
243                        p->prev = NULL;
244                        if (unit_head_large_first == NULL)
245                                p->next = NULL;
246                        else {
247                                unit_head_large_first->prev = p;
248                                p->next = unit_head_large_first;
249                        }
250                        unit_head_large_first = p;
251                        *(long*)((char*)p + sizeof(struct unit_head_large) - sizeof(long) + size) = 0xdeadbeaf;
252                        return (char *)p + sizeof(struct unit_head_large) - sizeof(long);
253                } else {
254                        ShowFatalError("Memory manager::memmgr_alloc failed (allocating %d+%d bytes at %s:%d).\n", sizeof(struct unit_head_large), size, file, line);
255                        exit(EXIT_FAILURE);
256                }
257        }
258
259        /* “¯ˆêƒTƒCƒY‚̃uƒƒbƒN‚ªŠm•Û‚³‚ê‚Ä‚¢‚È‚¢ŽžAV‚œ‚ÉŠm•Û‚·‚é */
260        if(hash_unfill[size_hash]) {
261                block = hash_unfill[size_hash];
262        } else {
263                block = block_malloc(size_hash);
264        }
265
266        if( block->unit_unfill == 0xFFFF ) {
267                // freeÏ‚ݗ̈悪Žc‚Á‚Ä‚¢‚È‚¢
268                memmgr_assert(block->unit_used <  block->unit_count);
269                memmgr_assert(block->unit_used == block->unit_maxused);
270                head = block2unit(block, block->unit_maxused);
271                block->unit_used++;
272                block->unit_maxused++;
273        } else {
274                head = block2unit(block, block->unit_unfill);
275                block->unit_unfill = head->size;
276                block->unit_used++;
277        }
278
279        if( block->unit_unfill == 0xFFFF && block->unit_maxused >= block->unit_count) {
280                // ƒ†ƒjƒbƒg‚ðŽg‚¢‰Ê‚œ‚µ‚œ‚̂ŁAunfillƒŠƒXƒg‚©‚çíœ
281                if( block->unfill_prev == &block_head) {
282                        hash_unfill[ size_hash ] = block->unfill_next;
283                } else {
284                        block->unfill_prev->unfill_next = block->unfill_next;
285                }
286                if( block->unfill_next ) {
287                        block->unfill_next->unfill_prev = block->unfill_prev;
288                }
289                block->unfill_prev = NULL;
290        }
291
292#ifdef DEBUG_MEMMGR
293        {
294                size_t i, sz = hash2size( size_hash );
295                for( i=0; i<sz; i++ )
296                {
297                        if( ((unsigned char*)head)[ sizeof(struct unit_head) - sizeof(long) + i] != 0xfd )
298                        {
299                                if( head->line != 0xfdfd )
300                                {
301                                        ShowError("Memory manager: freed-data is changed. (freed in %s line %d)\n", head->file,head->line);
302                                }
303                                else
304                                {
305                                        ShowError("Memory manager: not-allocated-data is changed.\n");
306                                }
307                                break;
308                        }
309                }
310                memset( (char *)head + sizeof(struct unit_head) - sizeof(long), 0xcd, sz );
311        }
312#endif
313
314        head->block = block;
315        head->file  = file;
316        head->line  = line;
317        head->size  = (unsigned short)size;
318        *(long*)((char*)head + sizeof(struct unit_head) - sizeof(long) + size) = 0xdeadbeaf;
319        return (char *)head + sizeof(struct unit_head) - sizeof(long);
320};
321
322void* _mcalloc(size_t num, size_t size, const char *file, int line, const char *func )
323{
324        void *p = _mmalloc(num * size,file,line,func);
325        memset(p,0,num * size);
326        return p;
327}
328
329void* _mrealloc(void *memblock, size_t size, const char *file, int line, const char *func )
330{
331        size_t old_size;
332        if(memblock == NULL) {
333                return _mmalloc(size,file,line,func);
334        }
335
336        old_size = ((struct unit_head *)((char *)memblock - sizeof(struct unit_head) + sizeof(long)))->size;
337        if( old_size == 0 ) {
338                old_size = ((struct unit_head_large *)((char *)memblock - sizeof(struct unit_head_large) + sizeof(long)))->size;
339        }
340        if(old_size > size) {
341                // ƒTƒCƒYk¬ -> ‚»‚̂܂ܕԂ·iŽè”²‚«j
342                return memblock;
343        }  else {
344                // ƒTƒCƒYŠg‘å
345                void *p = _mmalloc(size,file,line,func);
346                if(p != NULL) {
347                        memcpy(p,memblock,old_size);
348                }
349                _mfree(memblock,file,line,func);
350                return p;
351        }
352}
353
354char* _mstrdup(const char *p, const char *file, int line, const char *func )
355{
356        if(p == NULL) {
357                return NULL;
358        } else {
359                size_t len = strlen(p);
360                char *string  = (char *)_mmalloc(len + 1,file,line,func);
361                memcpy(string,p,len+1);
362                return string;
363        }
364}
365
366void _mfree(void *ptr, const char *file, int line, const char *func )
367{
368        struct unit_head *head;
369
370        if (ptr == NULL)
371                return; 
372
373        head = (struct unit_head *)((char *)ptr - sizeof(struct unit_head) + sizeof(long));
374        if(head->size == 0) {
375                /* malloc() ‚Å’Œ‚ÉŠm•Û‚³‚ꂜ—̈æ */
376                struct unit_head_large *head_large = (struct unit_head_large *)((char *)ptr - sizeof(struct unit_head_large) + sizeof(long));
377                if(
378                        *(long*)((char*)head_large + sizeof(struct unit_head_large) - sizeof(long) + head_large->size)
379                        != 0xdeadbeaf)
380                {
381                        ShowError("Memory manager: args of aFree 0x%p is overflowed pointer %s line %d\n", ptr, file, line);
382                } else {
383                        head->size = -1;
384                        if(head_large->prev) {
385                                head_large->prev->next = head_large->next;
386                        } else {
387                                unit_head_large_first  = head_large->next;
388                        }
389                        if(head_large->next) {
390                                head_large->next->prev = head_large->prev;
391                        }
392                        memmgr_usage_bytes -= head_large->size;
393#ifdef DEBUG_MEMMGR
394                        // set freed memory to 0xfd
395                        memset(ptr, 0xfd, head_large->size);
396#endif
397                        FREE(head_large,file,line,func);
398                }
399        } else {
400                /* ƒ†ƒjƒbƒg‰ð•ú */
401                struct block *block = head->block;
402                if( (char*)head - (char*)block > sizeof(struct block) ) {
403                        ShowError("Memory manager: args of aFree 0x%p is invalid pointer %s line %d\n", ptr, file, line);
404                } else if(head->block == NULL) {
405                        ShowError("Memory manager: args of aFree 0x%p is freed pointer %s:%d@%s\n", ptr, file, line, func);
406                } else if(*(long*)((char*)head + sizeof(struct unit_head) - sizeof(long) + head->size) != 0xdeadbeaf) {
407                        ShowError("Memory manager: args of aFree 0x%p is overflowed pointer %s line %d\n", ptr, file, line);
408                } else {
409                        memmgr_usage_bytes -= head->size;
410                        head->block         = NULL;
411#ifdef DEBUG_MEMMGR
412                        memset(ptr, 0xfd, block->unit_size - sizeof(struct unit_head) + sizeof(long) );
413                        head->file = file;
414                        head->line = line;
415#endif
416                        memmgr_assert( block->unit_used > 0 );
417                        if(--block->unit_used == 0) {
418                                /* ƒuƒƒbƒN‚̉ð•ú */
419                                block_free(block);
420                        } else {
421                                if( block->unfill_prev == NULL) {
422                                        // unfill ƒŠƒXƒg‚ɒljÁ
423                                        if( hash_unfill[ block->unit_hash ] ) {
424                                                hash_unfill[ block->unit_hash ]->unfill_prev = block;
425                                        }
426                                        block->unfill_prev = &block_head;
427                                        block->unfill_next = hash_unfill[ block->unit_hash ];
428                                        hash_unfill[ block->unit_hash ] = block;
429                                }
430                                head->size     = block->unit_unfill;
431                                block->unit_unfill = (unsigned short)(((unsigned long)head - (unsigned long)block->data) / block->unit_size);
432                        }
433                }
434        }
435}
436
437/* ƒuƒƒbƒN‚ðŠm•Û‚·‚é */
438static struct block* block_malloc(unsigned short hash)
439{
440        int i;
441        struct block *p;
442        if(hash_unfill[0] != NULL) {
443                /* ƒuƒƒbƒN—p‚̗̈æ‚ÍŠm•ÛÏ‚Ý */
444                p = hash_unfill[0];
445                hash_unfill[0] = hash_unfill[0]->unfill_next;
446        } else {
447                /* ƒuƒƒbƒN—p‚̗̈æ‚ðV‚œ‚ÉŠm•Û‚·‚é */
448                p = (struct block*)MALLOC(sizeof(struct block) * (BLOCK_ALLOC), __FILE__, __LINE__, __func__ );
449                if(p == NULL) {
450                        ShowFatalError("Memory manager::block_alloc failed.\n");
451                        exit(EXIT_FAILURE);
452                }
453
454                if(block_first == NULL) {
455                        /* ‰‰ñŠm•Û */
456                        block_first = p;
457                } else {
458                        block_last->block_next = p;
459                }
460                block_last = &p[BLOCK_ALLOC - 1];
461                block_last->block_next = NULL;
462                /* ƒuƒƒbƒN‚ð˜AŒ‹‚³‚¹‚é */
463                for(i=0;i<BLOCK_ALLOC;i++) {
464                        if(i != 0) {
465                                // p[0] ‚Í‚±‚ê‚©‚çŽg‚€‚Ì‚ÅƒŠƒ“ƒN‚ɂ͉Á‚Š‚È‚¢
466                                p[i].unfill_next = hash_unfill[0];
467                                hash_unfill[0]   = &p[i];
468                                p[i].unfill_prev = NULL;
469                                p[i].unit_used = 0;
470                        }
471                        if(i != BLOCK_ALLOC -1) {
472                                p[i].block_next = &p[i+1];
473                        }
474                }
475        }
476
477        // unfill ‚ɒljÁ
478        memmgr_assert(hash_unfill[ hash ] == NULL);
479        hash_unfill[ hash ] = p;
480        p->unfill_prev  = &block_head;
481        p->unfill_next  = NULL;
482        p->unit_size    = (unsigned short)(hash2size( hash ) + sizeof(struct unit_head));
483        p->unit_hash    = hash;
484        p->unit_count   = BLOCK_DATA_SIZE / p->unit_size;
485        p->unit_used    = 0;
486        p->unit_unfill  = 0xFFFF;
487        p->unit_maxused = 0;
488#ifdef DEBUG_MEMMGR
489        memset( p->data, 0xfd, sizeof(p->data) );
490#endif
491        return p;
492}
493
494static void block_free(struct block* p)
495{
496        if( p->unfill_prev ) {
497                if( p->unfill_prev == &block_head) {
498                        hash_unfill[ p->unit_hash ] = p->unfill_next;
499                } else {
500                        p->unfill_prev->unfill_next = p->unfill_next;
501                }
502                if( p->unfill_next ) {
503                        p->unfill_next->unfill_prev = p->unfill_prev;
504                }
505                p->unfill_prev = NULL;
506        }
507
508        p->unfill_next = hash_unfill[0];
509        hash_unfill[0] = p;
510}
511
512size_t memmgr_usage (void)
513{
514        return memmgr_usage_bytes / 1024;
515}
516
517#ifdef LOG_MEMMGR
518static char memmer_logfile[128];
519static FILE *log_fp;
520
521static void memmgr_log (char *buf)
522{
523        if( !log_fp )
524        {
525                time_t raw;
526                struct tm* t;
527
528                log_fp = fopen(memmer_logfile,"at");
529                if (!log_fp) log_fp = stdout;
530
531                time(&raw);
532                t = localtime(&raw);
533                fprintf(log_fp, "\nMemory manager: Memory leaks found at %d/%02d/%02d %02dh%02dm%02ds (Revision %s).\n",
534                        (t->tm_year+1900), (t->tm_mon+1), t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, get_svn_revision());
535        }
536        fprintf(log_fp, "%s", buf);
537        return;
538}
539#endif /* LOG_MEMMGR */
540
541/// Returns true if the memory location is active.
542/// Active means it is allocated and points to a usable part.
543///
544/// @param ptr Pointer to the memory
545/// @return true if the memory is active
546bool memmgr_verify(void* ptr)
547{
548        struct block* block = block_first;
549        struct unit_head_large* large = unit_head_large_first;
550
551        if( ptr == NULL )
552                return false;// never valid
553
554        // search small blocks
555        while( block )
556        {
557                if( (char*)ptr >= (char*)block && (char*)ptr < ((char*)block) + sizeof(struct block) )
558                {// found memory block
559                        if( block->unit_used && (char*)ptr >= block->data )
560                        {// memory block is being used and ptr points to a sub-unit
561                                size_t i = (size_t)((char*)ptr - block->data)/block->unit_size;
562                                struct unit_head* head = block2unit(block, i);
563                                if( i < block->unit_maxused && head->block != NULL )
564                                {// memory unit is allocated, check if ptr points to the usable part
565                                        return ( (char*)ptr >= ((char*)head) + sizeof(struct unit_head) - sizeof(long)
566                                                && (char*)ptr < ((char*)head) + sizeof(struct unit_head) - sizeof(long) + head->size );
567                                }
568                        }
569                        return false;
570                }
571                block = block->block_next;
572        }
573
574        // search large blocks
575        while( large )
576        {
577                if( (char*)ptr >= (char*)large && (char*)ptr < ((char*)large) + large->size )
578                {// found memory block, check if ptr points to the usable part
579                        return ( (char*)ptr >= ((char*)large) + sizeof(struct unit_head_large) - sizeof(long)
580                                && (char*)ptr < ((char*)large) + sizeof(struct unit_head_large) - sizeof(long) + large->size );
581                }
582                large = large->next;
583        }
584        return false;
585}
586
587static void memmgr_final (void)
588{
589        struct block *block = block_first;
590        struct unit_head_large *large = unit_head_large_first;
591
592#ifdef LOG_MEMMGR
593        int count = 0;
594#endif /* LOG_MEMMGR */
595
596        while (block) {
597                if (block->unit_used) {
598                        int i;
599                        for (i = 0; i < block->unit_maxused; i++) {
600                                struct unit_head *head = block2unit(block, i);
601                                if(head->block != NULL) {
602                                        char* ptr = (char *)head + sizeof(struct unit_head) - sizeof(long);
603#ifdef LOG_MEMMGR
604                                        char buf[1024];
605                                        sprintf (buf,
606                                                "%04d : %s line %d size %lu address 0x%p\n", ++count,
607                                                head->file, head->line, (unsigned long)head->size, ptr);
608                                        memmgr_log (buf);
609#endif /* LOG_MEMMGR */
610                                        // get block pointer and free it [celest]
611                                        _mfree(ptr, ALC_MARK);
612                                }
613                        }
614                }
615                block = block->block_next;
616        }
617
618        while(large) {
619                struct unit_head_large *large2;
620#ifdef LOG_MEMMGR
621                char buf[1024];
622                sprintf (buf,
623                        "%04d : %s line %d size %lu address 0x%p\n", ++count,
624                        large->unit_head.file, large->unit_head.line, (unsigned long)large->size, &large->unit_head.checksum);
625                memmgr_log (buf);
626#endif /* LOG_MEMMGR */
627                large2 = large->next;
628                FREE(large,file,line,func);
629                large = large2;
630        }
631#ifdef LOG_MEMMGR
632        if(count == 0) {
633                ShowInfo("Memory manager: No memory leaks found.\n");
634        } else {
635                ShowWarning("Memory manager: Memory leaks found and fixed.\n");
636                fclose(log_fp);
637        }
638#endif /* LOG_MEMMGR */
639        return;
640}
641
642static void memmgr_init (void)
643{
644#ifdef LOG_MEMMGR
645        sprintf(memmer_logfile, "log/%s.leaks", SERVER_NAME);
646        ShowStatus("Memory manager initialised: "CL_WHITE"%s"CL_RESET"\n", memmer_logfile);
647        memset(hash_unfill, 0, sizeof(hash_unfill));
648#endif /* LOG_MEMMGR */
649        return;
650}
651#endif /* USE_MEMMGR */
652
653
654/*======================================
655 * Initialise
656 *--------------------------------------
657 */
658
659bool malloc_verify(void* ptr)
660{
661#ifdef USE_MEMMGR
662        return memmgr_verify(ptr);
663#else
664        return true;
665#endif
666}
667
668size_t malloc_usage (void)
669{
670#ifdef USE_MEMMGR
671        return memmgr_usage ();
672#else
673        return 0;
674#endif
675}
676
677void malloc_final (void)
678{
679#ifdef USE_MEMMGR
680        memmgr_final ();
681#endif
682        return;
683}
684
685void malloc_init (void)
686{
687#ifdef USE_MEMMGR
688        memmgr_init ();
689#endif
690        return;
691}
Note: See TracBrowser for help on using the browser.