#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); } return ret; } 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); } return ret; } 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); } 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; } } void* aStrdup_(const void* string, const char *file, int line, const char *func ) { if(string == NULL) { return NULL; } else { int len = strlen(string); char *p = (char *)aMalloc_(len + 1,file,line,func); memcpy(p,string,len+1); return p; } } 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); } } int do_init_memmgr(const char* file) { sprintf(memmer_logfile,"%s.log",file); atexit(memmer_exit); printf("memmgr: initialised: %s\n",memmer_logfile); return 0; } #endif