📄 memblk.cpp
字号:
} tprintf ("\n"); } free (callers[callindex].counts); callers[callindex].counts = NULL; } }}/********************************************************************** * MEM_ALLOCATOR::check * * Check consistency of all memory controlled by this allocator. **********************************************************************/void MEM_ALLOCATOR::check( //check consistency const char *string, //context message INT8 level //level of check ) { MEMBLOCK *block; //current block MEMUNION *chunk; //current chunk MEMUNION *prevchunk; //previous chunk INT32 chunksize; //size of chunk INT32 usedcount; //no of used chunks INT32 usedsize; //size of used chunks INT32 freecount; //no of free chunks INT32 freesize; //size of free chunks INT32 biggest; //biggest free chunk INT32 totusedcount; //no of used chunks INT32 totusedsize; //size of used chunks INT32 totfreecount; //no of free chunks INT32 totfreesize; //size of free chunks INT32 totbiggest; //biggest free chunk INT32 totblocksize; //total size of blocks INT32 chunkindex; //index of chunk INT32 blockindex; //index of block if (level >= MEMCHECKS) tprintf ("\nMEM_ALLOCATOR::check:at '%s'\n", string); totusedcount = 0; //grand totals totusedsize = 0; totfreecount = 0; totfreesize = 0; totbiggest = 0; totblocksize = 0; for (blockindex = 0; blockindex < blockcount; blockindex++) { //current block block = &memblocks[blockindex]; if (level >= MEMCHECKS) tprintf ("Block %d:0x%x-0x%x, size=%d, top=0x%x, l=%d, u=%d\n", blockindex, block->blockstart, block->blockend, (block->blockend - block->blockstart) * sizeof (MEMUNION), block->topchunk, block->lowerspace, block->upperspace); usedcount = usedsize = 0; //zero counters freecount = freesize = 0; //zero counters biggest = 0; //scan all chunks for (chunkindex = 0, prevchunk = NULL, chunk = block->blockstart; chunk != block->blockend; chunkindex++, chunk += chunksize) { chunksize = chunk->size; //size of chunk if (chunksize < 0) chunksize = -chunksize; //absolute size if (level >= FULLMEMCHECKS) { tprintf ("%5d=%8d%c caller=%d, age=%d ", (int) chunkindex, chunksize * sizeof (MEMUNION), chunk->size < 0 ? 'U' : 'F', chunk->owner, chunk->age); if (chunkindex % 5 == 4) tprintf ("\n"); } //illegal sizes if (chunksize == 0 || chunk->size == -1 //out of bounds || chunk + chunksize - block->blockstart <= 0 || block->blockend - (chunk + chunksize) < 0) BADMEMCHUNKS.error ("check_mem", ABORT, "Block=%p, Prev chunk=%p, Chunk=%p, Size=%x", block, prevchunk, chunk, (int) chunk->size); else if (chunk->size < 0) { usedcount++; //used block usedsize += chunksize; } else { freecount++; //free block freesize += chunksize; if (chunksize > biggest) biggest = chunksize; } prevchunk = chunk; } if (level >= MEMCHECKS) { if (level >= FULLMEMCHECKS) tprintf ("\n"); tprintf ("%d chunks in use, total size=%d bytes\n", (int) usedcount, usedsize * sizeof (MEMUNION)); tprintf ("%d chunks free, total size=%d bytes\n", (int) freecount, freesize * sizeof (MEMUNION)); tprintf ("Largest free fragment=%d bytes\n", biggest * sizeof (MEMUNION)); } totusedcount += usedcount; //grand totals totusedsize += usedsize; totfreecount += freecount; totfreesize += freesize; if (biggest > totbiggest) totbiggest = biggest; totblocksize += block->blockend - block->blockstart; } if (level >= MEMCHECKS) { tprintf ("%d total blocks in use, total size=%d bytes\n", blockcount, totblocksize * sizeof (MEMUNION)); tprintf ("%d total chunks in use, total size=%d bytes\n", (int) totusedcount, totusedsize * sizeof (MEMUNION)); tprintf ("%d total chunks free, total size=%d bytes\n", (int) totfreecount, totfreesize * sizeof (MEMUNION)); tprintf ("Largest free fragment=%d bytes\n", totbiggest * sizeof (MEMUNION)); } if (level >= MEMCHECKS) display_counts();}/********************************************************************** * MEM_ALLOCATOR::alloc_p * * Allocate permanent space which will never be returned. * This space is allocated from the top end of a memory block to * avoid the fragmentation which would result from alternate use * of alloc_mem for permanent and temporary blocks. **********************************************************************/void *MEM_ALLOCATOR::alloc_p( //permanent space INT32 count, //block size to allocate void *caller //ptr to caller ) { MEMBLOCK *block; //current block MEMUNION *chunk; //current chunk if (count < 1 || count > biggestblock) //request too big MEMTOOBIG.error ("alloc_mem_p", ABORT, "%d", (int) count); count += sizeof (MEMUNION) - 1;//round up to word count /= sizeof (MEMUNION); count++; //and add one if (topblock == NULL) { topblock = new_block (count);//get first block currblock = topblock; if (topblock == NULL) { check_mem ("alloc_mem_p returning NULL", MEMCHECKS); return NULL; } } block = topblock; //current block do { chunk = block->topchunk; if (chunk->size < count) block = block->next; //try next block } //until all tried while (chunk->size < count && block != topblock); if (chunk->size < count) { //still no good chunk = (MEMUNION *) alloc ((count - 1) * sizeof (MEMUNION), caller); //try last resort if (chunk != NULL) return chunk; check_mem ("alloc_mem_p returning NULL", MEMCHECKS); return NULL; } block->upperspace -= count; //less above freechunk if (chunk->size > count) { chunk->size -= count; chunk += chunk->size; } chunk->size = -count; //mark as in use if (mem_mallocdepth > 0) { set_owner(chunk, caller); } else { chunk->owner = 0; chunk->age = 0; } return chunk + 1; //created chunk}/********************************************************************** * MEM_ALLOCATOR::alloc * * Return a pointer to a buffer of count bytes aligned for any type. **********************************************************************/void *MEM_ALLOCATOR::alloc( //get memory INT32 count, //no of bytes to get void *caller //ptr to caller ) { MEMBLOCK *block; //current block MEMUNION *chunk; //current chunk INT32 chunksize; //size of free chunk MEMUNION *chunkstart; //start of free chunk if (count < 1 || count > biggestblock) MEMTOOBIG.error ("alloc_mem", ABORT, "%d", (int) count); //request too big count += sizeof (MEMUNION) - 1;//round up to word count /= sizeof (MEMUNION); count++; //and add one if (currblock == NULL) { //get first block currblock = new_block (count); topblock = currblock; if (currblock == NULL) { check_mem ("alloc_mem returning NULL", MEMCHECKS); return NULL; } } block = currblock; //current block if (block->upperspace <= block->lowerspace) { //restart chunklist block->freechunk = block->blockstart; block->upperspace += block->lowerspace; block->lowerspace = 0; //correct space counts } chunk = block->freechunk; //current free chunk if (chunk->size < count) { //big enough? do { //search for free chunk chunk = block->find_chunk (count); if (chunk->size < count) block = block->next; //try next block } //until all tried while (chunk->size < count && block != currblock); if (chunk->size < count) { //still no good //get a new block currblock = new_block (count); topblock = currblock; //set perms here too if (currblock == NULL) { check_mem ("alloc_mem returning NULL", MEMCHECKS); return NULL; } block = currblock; chunk = block->freechunk; //bound to be big enough } } chunkstart = chunk; //start of chunk if (chunk == block->topchunk && chunk + count != block->blockend) block->topchunk += count; //top has moved block->upperspace -= count; //upper part used chunksize = chunk->size; //size of free chunk chunk->size = -count; //mark as used chunk += count; //next free space totalmem -= count; //no of free elements if (chunksize > count) //bigger than exact? //remaining space chunk->size = chunksize - count; else if (chunk == block->blockend) { chunk = block->blockstart; //restart block block->upperspace = block->lowerspace; block->lowerspace = 0; //fix space counts } block->freechunk = chunk; //next free block if (mem_mallocdepth > 0) { set_owner(chunkstart, caller); } else { chunkstart->owner = 0; chunkstart->age = 0; } chunkstart++; //start of block return chunkstart; //pointer to block}/********************************************************************** * MEM_ALLOCATOR::set_owner * * Set the owner and time stamp of the block and check if needed. **********************************************************************/void MEM_ALLOCATOR::set_owner( //get memory MEMUNION *chunkstart, //chunk to set void *caller //ptr to caller ) { UINT16 callindex; //hash code callindex = hash_caller (caller); chunkstart->owner = callindex; //store evidence chunkstart->age = malloc_serial; malloc_minor_serial++; if (malloc_minor_serial >= malloc_div_ratio) { malloc_minor_serial = 0; malloc_serial++; //count calls if (malloc_serial == 0) { //wrap around reduce_counts(); //fix serial numbers malloc_serial = MAX_INT16 + 1; //all worth double malloc_div_ratio += malloc_div_ratio; } } malloc_auto_count++; if (mem_checkfreq > 0 && malloc_auto_count >= (UINT32) mem_checkfreq) { malloc_auto_count = 0; check_mem ("Auto check", MEMCHECKS); }}/********************************************************************** * MEM_ALLOCATOR::dealloc * * Free a block allocated by alloc (or alloc_p). * It checks that the pointer is legal and maintains counts of the * amount of free memory above and below the current free pointer. **********************************************************************/void MEM_ALLOCATOR::dealloc( //free memory void *oldchunk, //chunk to free void *caller //ptr to caller ) { MEMUNION *chunk; //current chunk MEMBLOCK *block; //current block if (oldchunk == NULL) FREENULLPTR.error ("free_mem", ABORT, NULL); chunk = (MEMUNION *) oldchunk; block = currblock; //current block if (block == NULL) NOTMALLOCMEM.error ("free_mem", ABORT, NULL); do { block = block->next; } //outside the block while ((chunk - block->blockstart < 0 || block->blockend - chunk <= 0) && block != currblock); if (chunk - block->blockstart < 0 || block->blockend - chunk <= 0) //in no block NOTMALLOCMEM.error ("free_mem", ABORT, NULL); chunk--; //point to size if (chunk->size == 0) //zero size FREEILLEGALPTR.error ("free_mem", ABORT, NULL); else if (chunk->size > 0) //already free FREEFREEDBLOCK.error ("free_mem", ABORT, NULL); chunk->size = -chunk->size; //mark it free if (mem_freedepth > 0 && callers != NULL) { //count calls callers[chunk->owner].count_freeer (caller); } totalmem += chunk->size; //total free memory if (chunk - block->freechunk < 0) //extra below block->lowerspace += chunk->size; else //extra above block->upperspace += chunk->size;}/********************************************************************** * MEM_ALLOCATOR::new_block *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -