static void memmgr_final (void) { struct block *block = block_first; struct unit_head_large *large = unit_head_large_first; #ifdef LOG_MEMMGR int count = 0; #endif /* LOG_MEMMGR */ while (block) { if (block->unit_used) { int i; for (i = 0; i < block->unit_maxused; i++) { struct unit_head *head = block2unit (block, i); if (head->block != NULL) { char *ptr = (char *) head + sizeof (struct unit_head) - sizeof (long); #ifdef LOG_MEMMGR char buf[1024]; sprintf (buf, "%04d : %s line %d size %lu address 0x%p\n", ++count, head->file, head->line, (unsigned long) head->size, ptr); memmgr_log (buf); #endif /* LOG_MEMMGR */ // get block pointer and free it [celest] _mfree (ptr, ALC_MARK); } } } block = block->block_next; } while (large) { struct unit_head_large *large2; #ifdef LOG_MEMMGR char buf[1024]; sprintf (buf, "%04d : %s line %d size %lu address 0x%p\n", ++count, large->unit_head.file, large->unit_head.line, (unsigned long) large->size, &large->unit_head.checksum); memmgr_log (buf); #endif /* LOG_MEMMGR */ large2 = large->next; FREE (large, file, line, func); large = large2; } #ifdef LOG_MEMMGR if (count == 0) { ShowInfo ("Memory manager: No memory leaks found.\n"); } else { ShowWarning ("Memory manager: Memory leaks found and fixed.\n"); fclose (log_fp); } #endif /* LOG_MEMMGR */ }
/// Returns true if the memory location is active. /// Active means it is allocated and points to a usable part. /// /// @param ptr Pointer to the memory /// @return true if the memory is active bool memmgr_verify (void *ptr) { struct block *block = block_first; struct unit_head_large *large = unit_head_large_first; if (ptr == NULL) return false;// never valid // search small blocks while (block) { if ( (char *) ptr >= (char *) block && (char *) ptr < ( (char *) block) + sizeof (struct block)) { // found memory block if (block->unit_used && (char *) ptr >= block->data) { // memory block is being used and ptr points to a sub-unit size_t i = (size_t) ( (char *) ptr - block->data) / block->unit_size; struct unit_head *head = block2unit (block, i); if (i < block->unit_maxused && head->block != NULL) { // memory unit is allocated, check if ptr points to the usable part return ( (char *) ptr >= ( (char *) head) + sizeof (struct unit_head) - sizeof (long) && (char *) ptr < ( (char *) head) + sizeof (struct unit_head) - sizeof (long) + head->size); } } return false; } block = block->block_next; } // search large blocks while (large) { if ( (char *) ptr >= (char *) large && (char *) ptr < ( (char *) large) + large->size) { // found memory block, check if ptr points to the usable part return ( (char *) ptr >= ( (char *) large) + sizeof (struct unit_head_large) - sizeof (long) && (char *) ptr < ( (char *) large) + sizeof (struct unit_head_large) - sizeof (long) + large->size); } large = large->next; } return false; }
void* _mmalloc(size_t size, const char *file, int line, const char *func ) { struct block *block; short size_hash = size2hash( size ); struct unit_head *head; if (((long) size) < 0) { ShowError("_mmalloc: %d\n", size); return NULL; } if(size == 0) { return NULL; } memmgr_usage_bytes += size; /* To ensure the area that exceeds the length of the block, using malloc () to */ /* At that time, the distinction by assigning NULL to unit_head.block */ if(hash2size(size_hash) > BLOCK_DATA_SIZE - sizeof(struct unit_head)) { struct unit_head_large* p = (struct unit_head_large*)MALLOC(sizeof(struct unit_head_large)+size,file,line,func); if(p != NULL) { p->size = size; p->unit_head.block = NULL; p->unit_head.size = 0; p->unit_head.file = file; p->unit_head.line = line; p->prev = NULL; if (unit_head_large_first == NULL) p->next = NULL; else { unit_head_large_first->prev = p; p->next = unit_head_large_first; } unit_head_large_first = p; *(long*)((char*)p + sizeof(struct unit_head_large) - sizeof(long) + size) = 0xdeadbeaf; return (char *)p + sizeof(struct unit_head_large) - sizeof(long); } else { ShowFatalError("Memory manager::memmgr_alloc failed (allocating %d+%d bytes at %s:%d).\n", sizeof(struct unit_head_large), size, file, line); exit(EXIT_FAILURE); } } /* When a block of the same size is not ensured, to ensure a new */ if(hash_unfill[size_hash]) { block = hash_unfill[size_hash]; } else { block = block_malloc(size_hash); } if( block->unit_unfill == 0xFFFF ) { // there are no more free space that memmgr_assert(block->unit_used < block->unit_count); memmgr_assert(block->unit_used == block->unit_maxused); head = block2unit(block, block->unit_maxused); block->unit_used++; block->unit_maxused++; } else { head = block2unit(block, block->unit_unfill); block->unit_unfill = head->size; block->unit_used++; } if( block->unit_unfill == 0xFFFF && block->unit_maxused >= block->unit_count) { // Since I ran out of the unit, removed from the list unfill if( block->unfill_prev == &block_head) { hash_unfill[ size_hash ] = block->unfill_next; } else { block->unfill_prev->unfill_next = block->unfill_next; } if( block->unfill_next ) { block->unfill_next->unfill_prev = block->unfill_prev; } block->unfill_prev = NULL; } #ifdef DEBUG_MEMMGR { size_t i, sz = hash2size( size_hash ); for( i=0; i<sz; i++ ) { if( ((unsigned char*)head)[ sizeof(struct unit_head) - sizeof(long) + i] != 0xfd ) { if( head->line != 0xfdfd ) { ShowError("Memory manager: freed-data is changed. (freed in %s line %d)\n", head->file,head->line); } else { ShowError("Memory manager: not-allocated-data is changed.\n"); } break; } } memset( (char *)head + sizeof(struct unit_head) - sizeof(long), 0xcd, sz ); } #endif head->block = block; head->file = file; head->line = line; head->size = (unsigned short)size; *(long*)((char*)head + sizeof(struct unit_head) - sizeof(long) + size) = 0xdeadbeaf; return (char *)head + sizeof(struct unit_head) - sizeof(long); }
void* _mmalloc(size_t size, const char *file, int line, const char *func ) { struct block *block; short size_hash = size2hash( size ); struct unit_head *head; if (((long) size) < 0) { ShowError("_mmalloc: %d\n", size); return NULL; } if(size == 0) { return NULL; } memmgr_usage_bytes += size; /* ブロック長を超える領域の確保には、malloc() を用いる */ /* その際、unit_head.block に NULL を代入して区別する */ if(hash2size(size_hash) > BLOCK_DATA_SIZE - sizeof(struct unit_head)) { struct unit_head_large* p = (struct unit_head_large*)MALLOC(sizeof(struct unit_head_large)+size,file,line,func); if(p != NULL) { p->size = size; p->unit_head.block = NULL; p->unit_head.size = 0; p->unit_head.file = file; p->unit_head.line = line; p->prev = NULL; if (unit_head_large_first == NULL) p->next = NULL; else { unit_head_large_first->prev = p; p->next = unit_head_large_first; } unit_head_large_first = p; *(long*)((char*)p + sizeof(struct unit_head_large) - sizeof(long) + size) = 0xdeadbeaf; return (char *)p + sizeof(struct unit_head_large) - sizeof(long); } else { ShowFatalError("Memory manager::memmgr_alloc failed (allocating %d+%d bytes at %s:%d).\n", sizeof(struct unit_head_large), size, file, line); exit(EXIT_FAILURE); } } /* 同一サイズのブロックが確保されていない時、新たに確保する */ if(hash_unfill[size_hash]) { block = hash_unfill[size_hash]; } else { block = block_malloc(size_hash); } if( block->unit_unfill == 0xFFFF ) { // free済み領域が残っていない memmgr_assert(block->unit_used < block->unit_count); memmgr_assert(block->unit_used == block->unit_maxused); head = block2unit(block, block->unit_maxused); block->unit_used++; block->unit_maxused++; } else { head = block2unit(block, block->unit_unfill); block->unit_unfill = head->size; block->unit_used++; } if( block->unit_unfill == 0xFFFF && block->unit_maxused >= block->unit_count) { // ユニットを使い果たしたので、unfillリストから削除 if( block->unfill_prev == &block_head) { hash_unfill[ size_hash ] = block->unfill_next; } else { block->unfill_prev->unfill_next = block->unfill_next; } if( block->unfill_next ) { block->unfill_next->unfill_prev = block->unfill_prev; } block->unfill_prev = NULL; } #ifdef DEBUG_MEMMGR { size_t i, sz = hash2size( size_hash ); for( i=0; i<sz; i++ ) { if( ((unsigned char*)head)[ sizeof(struct unit_head) - sizeof(long) + i] != 0xfd ) { if( head->line != 0xfdfd ) { ShowError("Memory manager: freed-data is changed. (freed in %s line %d)\n", head->file,head->line); } else { ShowError("Memory manager: not-allocated-data is changed.\n"); } break; } } memset( (char *)head + sizeof(struct unit_head) - sizeof(long), 0xcd, sz ); } #endif head->block = block; head->file = file; head->line = line; head->size = (unsigned short)size; *(long*)((char*)head + sizeof(struct unit_head) - sizeof(long) + size) = 0xdeadbeaf; return (char *)head + sizeof(struct unit_head) - sizeof(long); };
void* AdrenoMM_Alloc(unsigned int size, const char *file, int line, const char *func ) { struct block *block; short size_hash = size2hash( size ); struct unit_head *head; if(size == 0) { return NULL; } memmgr_usage_bytes += size; if (memmgr_usage_bytes > memmgr_max_used_bytes) memmgr_max_used_bytes = memmgr_usage_bytes; /* �u���b�N������̈�̊m�ۂɂ́Amalloc() ��p���� */ /* ���̍ہAunit_head.block �� NULL �������ċ�ʂ��� */ if(hash2size(size_hash) > BLOCK_DATA_SIZE - sizeof(struct unit_head)) { struct unit_head_large* p = (struct unit_head_large*)MALLOC(sizeof(struct unit_head_large)+size,file,line,func); if(p != NULL) { p->size = size; p->unit_head.block = NULL; p->unit_head.size = 0; p->unit_head.file = file; p->unit_head.line = line; p->prev = NULL; if (unit_head_large_first == NULL) p->next = NULL; else { unit_head_large_first->prev = p; p->next = unit_head_large_first; } unit_head_large_first = p; *(long*)((char*)p + sizeof(struct unit_head_large) - sizeof(long) + size) = 0xdeadbeaf; return (char *)p + sizeof(struct unit_head_large) - sizeof(long); } else { printf("Memory manager::memmgr_alloc failed (allocating %ld+%d bytes at %s:%d).\n", sizeof(struct unit_head_large), size, file, line); exit(EXIT_FAILURE); } } /* ����T�C�Y�̃u���b�N���m�ۂ���Ă��Ȃ����A�V���Ɋm�ۂ��� */ if(hash_unfill[size_hash]) { block = hash_unfill[size_hash]; } else { block = block_malloc(size_hash); } if( block->unit_unfill == 0xFFFF ) { // free�ςݗ̈悪�c���Ă��Ȃ� memmgr_assert(block->unit_used < block->unit_count); memmgr_assert(block->unit_used == block->unit_maxused); head = block2unit(block, block->unit_maxused); block->unit_used++; block->unit_maxused++; } else { head = block2unit(block, block->unit_unfill); block->unit_unfill = head->size; block->unit_used++; } if( block->unit_unfill == 0xFFFF && block->unit_maxused >= block->unit_count) { // ���j�b�g���g���ʂ������̂ŁAunfill���X�g����폜 if( block->unfill_prev == &block_head) { hash_unfill[ size_hash ] = block->unfill_next; } else { block->unfill_prev->unfill_next = block->unfill_next; } if( block->unfill_next ) { block->unfill_next->unfill_prev = block->unfill_prev; } block->unfill_prev = NULL; } #ifdef DEBUG_MEMMGR { unsigned int i, sz = hash2size( size_hash ); for( i=0; i<sz; i++ ) { if( ((unsigned char*)head)[ sizeof(struct unit_head) - sizeof(long) + i] != 0xfd ) { if( head->line != 0xfdfd ) { printf("Memory manager: freed-data is changed. (freed in %s line %d)\n", head->file,head->line); } else { printf("Memory manager: not-allocated-data is changed.\n"); } break; } } memset( (char *)head + sizeof(struct unit_head) - sizeof(long), 0xcd, sz ); } #endif head->block = block; head->file = file; head->line = line; head->size = (unsigned short)size; *(long*)((char*)head + sizeof(struct unit_head) - sizeof(long) + size) = 0xdeadbeaf; return (char *)head + sizeof(struct unit_head) - sizeof(long); };