123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547 |
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "malloc.h"
- #ifdef MEMWATCH
- #include "memwatch.h"
- #endif
- // 独自メモリマネージャを使用する場合、次のコメントを外してください。
- // #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 */
- /*
- * メモリマネージャ
- * malloc , free の処理を効率的に出来るようにしたもの。
- * 複雑な処理を行っているので、若干重くなるかもしれません。
- *
- * データ構造など(説明下手ですいません^^; )
- * ・メモリを複数の「ブロック」に分けて、さらにブロックを複数の「ユニット」
- * に分けています。ユニットのサイズは、1ブロックの容量を複数個に均等配分
- * したものです。たとえば、1ユニット32KBの場合、ブロック1つは32Byteのユ
- * ニットが、1024個集まって出来ていたり、64Byteのユニットが 512個集まって
- * 出来ていたりします。(padding,unit_head を除く)
- *
- * ・ユニット同士はリンクリスト(block_prev,block_next) でつながり、同じサイ
- * ズを持つユニット同士もリンクリスト(samesize_prev,samesize_nect) でつな
- * がっています。それにより、不要となったメモリの再利用が効率的に行えます。
- */
- /* ブロックに入るデータ量 */
- #define BLOCK_DATA_SIZE 80*1024
- /* 一度に確保するブロックの数。 */
- #define BLOCK_ALLOC 32
- /* ブロックのアライメント */
- #define BLOCK_ALIGNMENT 64
- /* ブロック */
- struct block {
- int block_no; /* ブロック番号 */
- struct block* block_prev; /* 前に確保した領域 */
- struct block* block_next; /* 次に確保した領域 */
- int samesize_no; /* 同じサイズの番号 */
- struct block* samesize_prev; /* 同じサイズの前の領域 */
- struct block* samesize_next; /* 同じサイズの次の領域 */
- int unit_size; /* ユニットのバイト数 0=未使用 */
- int unit_hash; /* ユニットのハッシュ */
- int unit_count; /* ユニットの数 */
- int unit_used; /* 使用済みユニット */
- 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;
- /* ユニットへのハッシュ。80KB/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]; /* 最後 */
- /* メモリを使い回せない領域用のデータ */
- 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; /* アライメントの倍数に切り上げ */
- if(size == 0) {
- return NULL;
- }
- /* ブロック長を超える領域の確保には、malloc() を用いる */
- /* その際、unit_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);
- }
- }
- /* 同一サイズのブロックが確保されていない時、新たに確保する */
- if(unit_unfill[size_hash] == NULL) {
- block = block_malloc();
- if(unit_first[size_hash] == NULL) {
- /* 初回確保 */
- unit_first[size_hash] = block;
- unit_last[size_hash] = block;
- block->samesize_no = 0;
- block->samesize_prev = NULL;
- block->samesize_next = NULL;
- } else {
- /* 連結作業 */
- 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;
- /* 未使用Flagを立てる */
- for(i=0;i<block->unit_count;i++) {
- ((struct unit_head*)(&block->data[block->unit_size * i]))->block = NULL;
- }
- }
- /* ユニット使用個数加算 */
- block = unit_unfill[size_hash];
- block->unit_used++;
- /* ユニット内を全て使い果たした */
- 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
- );
- }
- /* ブロックの中の空きユニット捜索 */
- 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);
- }
- }
- // ここに来てはいけない。
- 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) {
- // サイズ縮小 -> そのまま返す(手抜き)
- return memblock;
- } else {
- // サイズ拡大
- 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() で直に確保された領域 */
- 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 {
- /* ユニット解放 */
- 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) {
- /* ブロックの解放 */
- if(unit_unfill[block->unit_hash] == block) {
- /* 空きユニットに指定されている */
- 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) {
- /* 独立ブロックの解放 */
- unit_first[block->unit_hash] = NULL;
- unit_last[block->unit_hash] = NULL;
- unit_unfill[block->unit_hash] = NULL;
- } else if(block->samesize_prev == NULL) {
- /* 先頭ブロックの解放 */
- unit_first[block->unit_hash] = block->samesize_next;
- (block->samesize_next)->samesize_prev = NULL;
- } else if(block->samesize_next == NULL) {
- /* 末端ブロックの解放 */
- unit_last[block->unit_hash] = block->samesize_prev;
- (block->samesize_prev)->samesize_next = NULL;
- } else {
- /* 中間ブロックの解放 */
- (block->samesize_next)->samesize_prev = block->samesize_prev;
- (block->samesize_prev)->samesize_next = block->samesize_next;
- }
- block_free(block);
- } else {
- /* 空きユニットの再設定 */
- 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;
- }
- }
- /* ブロックを確保する */
- static struct block* block_malloc(void) {
- if(block_unused != NULL) {
- /* ブロック用の領域は確保済み */
- struct block* ret = block_unused;
- do {
- block_unused = block_unused->block_next;
- } while(block_unused != NULL && block_unused->unit_size != 0);
- return ret;
- } else {
- /* ブロック用の領域を新たに確保する */
- 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) {
- /* 初回確保 */
- 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];
- /* ブロックを連結させる */
- 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;
- }
- /* 未使用ブロックへのポインタを更新 */
- block_unused = &p[1];
- p->unit_size = 1;
- return p;
- }
- }
- static void block_free(struct block* p) {
- /* free() せずに、未使用フラグを付けるだけ */
- p->unit_size = 0;
- /* 未使用ポインターを更新する */
- 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
|