diff options
Diffstat (limited to 'src/common/malloc.c')
-rw-r--r-- | src/common/malloc.c | 510 |
1 files changed, 507 insertions, 3 deletions
diff --git a/src/common/malloc.c b/src/common/malloc.c index eda9bc218..b81c25ed5 100644 --- a/src/common/malloc.c +++ b/src/common/malloc.c @@ -1,13 +1,27 @@ #include <stdio.h> #include <stdlib.h> +#include <string.h> #include "malloc.h" +#ifdef MEMWATCH +#include "memwatch.h" +#endif + +// �Ǝ��������}�l�[�W�����g�p����ꍇ�A���̃R�����g���O���Ă��������B +//#define USE_MEMMGR + +#if !defined(DMALLOC) && !defined(GCOLLECT) && !defined(BCHECK) && !defined(USE_MEMMGR) + void* aMalloc_( size_t size, const char *file, int line, const char *func ) { void *ret; - + // printf("%s:%d: in func %s: malloc %d\n",file,line,func,size); +#ifdef MEMWATCH + ret=mwMalloc(size,file,line); +#else ret=malloc(size); +#endif if(ret==NULL){ printf("%s:%d: in func %s: malloc error out of memory!\n",file,line,func); exit(1); @@ -18,9 +32,13 @@ void* aMalloc_( size_t size, const char *file, int line, const char *func ) void* aCalloc_( size_t num, size_t size, const char *file, int line, const char *func ) { void *ret; - + // printf("%s:%d: in func %s: calloc %d %d\n",file,line,func,num,size); +#ifdef MEMWATCH + ret=mwCalloc(num,size,file,line); +#else ret=calloc(num,size); +#endif if(ret==NULL){ printf("%s:%d: in func %s: calloc error out of memory!\n",file,line,func); exit(1); @@ -32,9 +50,13 @@ void* aCalloc_( size_t num, size_t size, const char *file, int line, const char void* aRealloc_( void *p, size_t size, const char *file, int line, const char *func ) { void *ret; - + // printf("%s:%d: in func %s: realloc %p %d\n",file,line,func,p,size); +#ifdef MEMWATCH + ret=mwRealloc(p,size,file,line); +#else ret=realloc(p,size); +#endif if(ret==NULL){ printf("%s:%d: in func %s: realloc error out of memory!\n",file,line,func); exit(1); @@ -42,3 +64,485 @@ void* aRealloc_( void *p, size_t size, const char *file, int line, const char *f } return ret; } + +char* aStrdup_( const void *p, const char *file, int line, const char *func ) +{ + char *ret; + + // printf("%s:%d: in func %s: strdup %p\n",file,line,func,p); +#ifdef MEMWATCH + ret=mwStrdup(p,file,line); +#else + ret= strdup((char *) p); +#endif + if(ret==NULL){ + printf("%s:%d: in func %s: strdup error out of memory!\n",file,line,func); + exit(1); + + } + return ret; +} + +void aFree_( void *p, const char *file, int line, const char *func ) +{ + // printf("%s:%d: in func %s: free %p\n",file,line,func,p); +#ifdef MEMWATCH + mwFree(p,file,line); +#else + free(p); +#endif +} + +#elif defined(GCOLLECT) + +void * _bcallocA(size_t size, size_t cnt) { + void *ret = aMallocA(size * cnt); + memset(ret, 0, size * cnt); + return ret; +} + +void * _bcalloc(size_t size, size_t cnt) { + void *ret = aMalloc(size * cnt); + memset(ret, 0, size * cnt); + return ret; +} + +char * _bstrdup(const char *chr) { + int len = strlen(chr); + char *ret = (char*)aMalloc(len + 1); + strcpy(ret, chr); + return ret; +} + +#elif defined(USE_MEMMGR) + +/* USE_MEMMGR */ + +/* + * �������}�l�[�W�� + * malloc , free �̏����������I�ɏo����悤�ɂ������́B + * ���G�ȏ������s���Ă���̂ŁA��d���Ȃ邩������܂���B + * + * �f�[�^�\���Ȃǁi��������ł����܂���^^; �j + * �E���������́u�u���b�N�v�ɕ����āA����Ƀu���b�N���́u���j�b�g�v + * �ɕ����Ă��܂��B���j�b�g�̃T�C�Y�́A�P�u���b�N�̗e�ʂ��ɋϓ��z�� + * �������̂ł��B���Ƃ��A�P���j�b�g32KB�̏ꍇ�A�u���b�N�P��32Byte�̃� + * �j�b�g���A1024�W�܂��ďo���Ă�����A64Byte�̃��j�b�g�� 512�W�܂��� + * �o���Ă����肵�܂��B�ipadding,unit_head �������j + * + * �E���j�b�g���m�̓����N���X�g(block_prev,block_next) �łȂ���A�����T�C + * �Y�������j�b�g���m�������N���X�g(samesize_prev,samesize_nect) �ł� + * �����Ă��܂��B����ɂ��A�s�v�ƂȂ����������̍ė��p�������I�ɍs���܂��B + */ + +/* �u���b�N�ɓ���f�[�^�� */ +#define BLOCK_DATA_SIZE 80*1024 + +/* ��x�Ɋm�ۂ���u���b�N�̐��B */ +#define BLOCK_ALLOC 32 + +/* �u���b�N�̃A���C�����g */ +#define BLOCK_ALIGNMENT 64 + +/* �u���b�N */ +struct block { + int block_no; /* �u���b�N�ԍ� */ + struct block* block_prev; /* �O�Ɋm�ۂ����̈� */ + struct block* block_next; /* ���Ɋm�ۂ����̈� */ + int samesize_no; /* �����T�C�Y�̔ԍ� */ + struct block* samesize_prev; /* �����T�C�Y�̑O�̗̈� */ + struct block* samesize_next; /* �����T�C�Y�̎��̗̈� */ + int unit_size; /* ���j�b�g�̃o�C�g�� 0=���g�p */ + int unit_hash; /* ���j�b�g�̃n�b�V�� */ + int unit_count; /* ���j�b�g�̐� */ + int unit_used; /* �g�p�ς݃��j�b�g */ + char data[BLOCK_DATA_SIZE]; +}; + +struct unit_head { + struct block* block; + int size; + const char* file; + int line; +}; + +static struct block* block_first = NULL; +static struct block* block_last = NULL; +static struct block* block_unused = NULL; + +/* ���j�b�g�ւ̃n�b�V���B80KB/64Byte = 1280�� */ +static struct block* unit_first[BLOCK_DATA_SIZE/BLOCK_ALIGNMENT]; /* �ŏ� */ +static struct block* unit_unfill[BLOCK_DATA_SIZE/BLOCK_ALIGNMENT]; /* ���܂��ĂȂ� */ +static struct block* unit_last[BLOCK_DATA_SIZE/BLOCK_ALIGNMENT]; /* �Ō� */ + +/* ���������g���Ȃ��̈�p�̃f�[�^ */ +struct unit_head_large { + struct unit_head_large* prev; + struct unit_head_large* next; + struct unit_head unit_head; +}; +static struct unit_head_large *unit_head_large_first = NULL; + +static struct block* block_malloc(void); +static void block_free(struct block* p); +static void memmgr_info(void); + +void* aMalloc_(size_t size, const char *file, int line, const char *func ) { + int i; + struct block *block; + int size_hash = (size+BLOCK_ALIGNMENT-1) / BLOCK_ALIGNMENT; + size = size_hash * BLOCK_ALIGNMENT; /* �A���C�����g�̔{���ɐ�グ */ + + if(size == 0) { + return NULL; + } + + /* �u���b�N������̈�̊m�ۂɂ́Amalloc() ��p���� */ + /* ���̍ہAunit_head.block �� NULL �������ċ�ʂ��� */ + if(size > BLOCK_DATA_SIZE - sizeof(struct unit_head)) { +#ifdef MEMWATCH + struct unit_head_large* p = (struct unit_head_large*)mwMalloc(sizeof(struct unit_head_large) + size,file,line); +#else + struct unit_head_large* p = (struct unit_head_large*)malloc(sizeof(struct unit_head_large) + size); +#endif + if(p != NULL) { + p->unit_head.block = NULL; + p->unit_head.size = size; + p->unit_head.file = file; + p->unit_head.line = line; + if(unit_head_large_first == NULL) { + unit_head_large_first = p; + p->next = NULL; + p->prev = NULL; + } else { + unit_head_large_first->prev = p; + p->prev = NULL; + p->next = unit_head_large_first; + unit_head_large_first = p; + } + return (char *)p + sizeof(struct unit_head_large); + } else { + printf("MEMMGR::memmgr_alloc failed.\n"); + exit(1); + } + } + + /* ����T�C�Y�̃u���b�N���m�ۂ���Ă��Ȃ����A�V���Ɋm�ۂ��� */ + if(unit_unfill[size_hash] == NULL) { + block = block_malloc(); + if(unit_first[size_hash] == NULL) { + /* ����m�� */ + unit_first[size_hash] = block; + unit_last[size_hash] = block; + block->samesize_no = 0; + block->samesize_prev = NULL; + block->samesize_next = NULL; + } else { + /* �A����� */ + unit_last[size_hash]->samesize_next = block; + block->samesize_no = unit_last[size_hash]->samesize_no + 1; + block->samesize_prev = unit_last[size_hash]; + block->samesize_next = NULL; + unit_last[size_hash] = block; + } + unit_unfill[size_hash] = block; + block->unit_size = size + sizeof(struct unit_head); + block->unit_count = BLOCK_DATA_SIZE / block->unit_size; + block->unit_used = 0; + block->unit_hash = size_hash; + /* ���g�pFlag�𗧂Ă� */ + for(i=0;i<block->unit_count;i++) { + ((struct unit_head*)(&block->data[block->unit_size * i]))->block = NULL; + } + } + /* ���j�b�g�g�p�����Z */ + block = unit_unfill[size_hash]; + block->unit_used++; + + /* ���j�b�g����S�Ďg���ʂ����� */ + if(block->unit_count == block->unit_used) { + do { + unit_unfill[size_hash] = unit_unfill[size_hash]->samesize_next; + } while( + unit_unfill[size_hash] != NULL && + unit_unfill[size_hash]->unit_count == unit_unfill[size_hash]->unit_used + ); + } + + /* �u���b�N�̒��̋��j�b�g�{�� */ + for(i=0;i<block->unit_count;i++) { + struct unit_head *head = (struct unit_head*)(&block->data[block->unit_size * i]); + if(head->block == NULL) { + head->block = block; + head->size = size; + head->line = line; + head->file = file; + return (char *)head + sizeof(struct unit_head); + } + } + // �����ɗ��Ă͂����Ȃ��B + printf("MEMMGR::memmgr_malloc() serious error.\n"); + memmgr_info(); + exit(1); + return NULL; +}; + +void* aCalloc_(size_t num, size_t size, const char *file, int line, const char *func ) { + void *p = aMalloc_(num * size,file,line,func); + memset(p,0,num * size); + return p; +} + +void* aRealloc_(void *memblock, size_t size, const char *file, int line, const char *func ) { + size_t old_size; + if(memblock == NULL) { + return aMalloc_(size,file,line,func); + } + + old_size = ((struct unit_head *)((char *)memblock - sizeof(struct unit_head)))->size; + if(old_size > size) { + // �T�C�Y�k�� -> ���̂܂ܕԂ��i�蔲���j + return memblock; + } else { + // �T�C�Y�g�� + void *p = aMalloc_(size,file,line,func); + if(p != NULL) { + memcpy(p,memblock,old_size); + } + aFree_(memblock,file,line,func); + return p; + } +} + +char* aStrdup_(const void *p, const char *file, int line, const char *func ) { + if(p == NULL) { + return NULL; + } else { + int len = strlen(p); + char *string = (char *)aMalloc_(len + 1,file,line,func); + memcpy(string,p,len+1); + return string; + } +} + +void aFree_(void *ptr, const char *file, int line, const char *func ) { + struct unit_head *head = (struct unit_head *)((char *)ptr - sizeof(struct unit_head)); + if(ptr == NULL) { + return; + } else if(head->block == NULL && head->size > BLOCK_DATA_SIZE - sizeof(struct unit_head)) { + /* malloc() �Œ��Ɋm�ۂ��ꂽ�̈� */ + struct unit_head_large *head_large = (struct unit_head_large *)((char *)ptr - sizeof(struct unit_head_large)); + if(head_large->prev) { + head_large->prev->next = head_large->next; + } else { + unit_head_large_first = head_large->next; + } + if(head_large->next) { + head_large->next->prev = head_large->prev; + } + free(head_large); + return; + } else { + /* ���j�b�g��� */ + struct block *block = head->block; + if(head->block == NULL) { + printf("memmgr: args of aFree is freed pointer %s line %d\n",file,line); + } else { + head->block = NULL; + if(--block->unit_used == 0) { + /* �u���b�N�̉�� */ + if(unit_unfill[block->unit_hash] == block) { + /* ���j�b�g�Ɏw�肳��Ă��� */ + do { + unit_unfill[block->unit_hash] = unit_unfill[block->unit_hash]->samesize_next; + } while( + unit_unfill[block->unit_hash] != NULL && + unit_unfill[block->unit_hash]->unit_count == unit_unfill[block->unit_hash]->unit_used + ); + } + if(block->samesize_prev == NULL && block->samesize_next == NULL) { + /* �Ɨ��u���b�N�̉�� */ + unit_first[block->unit_hash] = NULL; + unit_last[block->unit_hash] = NULL; + unit_unfill[block->unit_hash] = NULL; + } else if(block->samesize_prev == NULL) { + /* �擪�u���b�N�̉�� */ + unit_first[block->unit_hash] = block->samesize_next; + (block->samesize_next)->samesize_prev = NULL; + } else if(block->samesize_next == NULL) { + /* ���[�u���b�N�̉�� */ + unit_last[block->unit_hash] = block->samesize_prev; + (block->samesize_prev)->samesize_next = NULL; + } else { + /* ���ԃu���b�N�̉�� */ + (block->samesize_next)->samesize_prev = block->samesize_prev; + (block->samesize_prev)->samesize_next = block->samesize_next; + } + block_free(block); + } else { + /* ���j�b�g�̍Đݒ� */ + if( + unit_unfill[block->unit_hash] == NULL || + unit_unfill[block->unit_hash]->samesize_no > block->samesize_no + ) { + unit_unfill[block->unit_hash] = block; + } + } + } + } +} + +/* ���݂̏�\������ */ +static void memmgr_info(void) { + int i; + struct block *p; + printf("** Memory Maneger Information **\n"); + if(block_first == NULL) { + printf("Uninitialized.\n"); + return; + } + printf( + "Blocks: %04u , BlockSize: %06u Byte , Used: %08uKB\n", + block_last->block_no+1,sizeof(struct block), + (block_last->block_no+1) * sizeof(struct block) / 1024 + ); + p = block_first; + for(i=0;i<=block_last->block_no;i++) { + printf(" Block #%04u : ",p->block_no); + if(p->unit_size == 0) { + printf("unused.\n"); + } else { + printf( + "size: %05u byte. used: %04u/%04u prev:", + p->unit_size - sizeof(struct unit_head),p->unit_used,p->unit_count + ); + if(p->samesize_prev == NULL) { + printf("NULL"); + } else { + printf("%04u",(p->samesize_prev)->block_no); + } + printf(" next:"); + if(p->samesize_next == NULL) { + printf("NULL"); + } else { + printf("%04u",(p->samesize_next)->block_no); + } + printf("\n"); + } + p = p->block_next; + } +} + +/* �u���b�N���m�ۂ��� */ +static struct block* block_malloc(void) { + if(block_unused != NULL) { + /* �u���b�N�p�̗̈�͊m�ۍς� */ + struct block* ret = block_unused; + do { + block_unused = block_unused->block_next; + } while(block_unused != NULL && block_unused->unit_size != 0); + return ret; + } else { + /* �u���b�N�p�̗̈��V���Ɋm�ۂ��� */ + int i; + int block_no; + struct block* p = (struct block *)calloc(sizeof(struct block),BLOCK_ALLOC); + if(p == NULL) { + printf("MEMMGR::block_alloc failed.\n"); + exit(1); + } + if(block_first == NULL) { + /* ����m�� */ + block_no = 0; + block_first = p; + } else { + block_no = block_last->block_no + 1; + block_last->block_next = p; + p->block_prev = block_last; + } + block_last = &p[BLOCK_ALLOC - 1]; + /* �u���b�N��A�������� */ + for(i=0;i<BLOCK_ALLOC;i++) { + if(i != 0) { + p[i].block_prev = &p[i-1]; + } + if(i != BLOCK_ALLOC -1) { + p[i].block_next = &p[i+1]; + } + p[i].block_no = block_no + i; + } + + /* ���g�p�u���b�N�ւ̃|�C���^���X�V */ + block_unused = &p[1]; + p->unit_size = 1; + return p; + } +} + +static void block_free(struct block* p) { + /* free() �����ɁA���g�p�t���O��t���邾�� */ + p->unit_size = 0; + /* ���g�p�|�C���^�[���X�V���� */ + if(block_unused == NULL) { + block_unused = p; + } else if(block_unused->block_no > p->block_no) { + block_unused = p; + } +} + +static char memmer_logfile[128]; + +static FILE* memmgr_log(void) { + FILE *fp = fopen(memmer_logfile,"w"); + if(!fp) { fp = stdout; } + fprintf(fp,"memmgr: memory leaks found\n"); + return fp; +} + +static void memmer_exit(void) { + FILE *fp = NULL; + int i; + int count = 0; + struct block *block = block_first; + struct unit_head_large *large = unit_head_large_first; + while(block) { + if(block->unit_size) { + if(!fp) { fp = memmgr_log(); } + for(i=0;i<block->unit_count;i++) { + struct unit_head *head = (struct unit_head*)(&block->data[block->unit_size * i]); + if(head->block != NULL) { + fprintf( + fp,"%04d : %s line %d size %d\n",++count, + head->file,head->line,head->size + ); + } + } + } + block = block->block_next; + } + while(large) { + if(!fp) { fp = memmgr_log(); } + fprintf( + fp,"%04d : %s line %d size %d\n",++count, + large->unit_head.file, + large->unit_head.line,large->unit_head.size + ); + large = large->next; + } + if(!fp) { + printf("memmgr: no memory leaks found.\n"); + } else { + printf("memmgr: memory leaks found.\n"); + fclose(fp); + } +} +#endif + +int do_init_memmgr(const char* file) { + #ifdef USE_MEMMGR + sprintf(memmer_logfile,"%s.log",file); + atexit(memmer_exit); + printf("memmgr: initialised: %s\n",memmer_logfile); + #endif + return 0; +} |