📄 memblk.cpp
字号:
/********************************************************************** * File: memblk.c (Formerly memblock.c) * Description: Enhanced instrumented memory allocator implemented as a class. * Author: Ray Smith * Created: Tue Jan 21 17:13:39 GMT 1992 * * (C) Copyright 1992, Hewlett-Packard Ltd. ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** http://www.apache.org/licenses/LICENSE-2.0 ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. * **********************************************************************/#include "mfcpch.h" //precompiled headers#include <stdlib.h>#include <string.h>#include "stderr.h"#include "memryerr.h"#include "hashfn.h"#include "tprintf.h"#include "memry.h"#include "memblk.h"#ifdef __UNIX__#include <signal.h>#endifclass UWREC{ public: unsigned cur_frsize; //frame size unsigned cursp; //stack unsigned currls; //pc space unsigned currlo; //pc offset unsigned curdp; //data pointer unsigned toprp; //rp unsigned topmrp; //mrp unsigned topsr0; //sr0 unsigned topsr4; //sr4 unsigned r3; //gr3 unsigned cur_r19; //gr19};MEMUNION *free_block = NULL; //head of freelist#define EXTERNEXTERN MEM_ALLOCATOR big_mem;EXTERN MEM_ALLOCATOR main_mem; //heads of freelistsEXTERN MEMUNION *free_structs[MAX_STRUCTS]; //number issuedEXTERN INT32 structs_in_use[MAX_STRUCTS]; //number issuedEXTERN INT32 blocks_in_use[MAX_STRUCTS]; //head of block listsEXTERN MEMUNION *struct_blocks[MAX_STRUCTS];EXTERN const char *owner_names[MAX_STRUCTS][MAX_CLASSES];EXTERN INT32 owner_counts[MAX_STRUCTS][MAX_CLASSES]; //no of namesEXTERN INT16 name_counts[MAX_STRUCTS];EXTERN INT32 free_struct_blocks; //no of free blocksEXTERN INT_VAR (mem_mallocdepth, 0, "Malloc stack depth to trace");EXTERN INT_VAR (mem_mallocbits, 8, "Log 2 of hash table size");EXTERN INT_VAR (mem_freedepth, 0, "Free stack dpeth to trace");EXTERN INT_VAR (mem_freebits, 8, "Log 2 of hash table size");EXTERN INT_VAR (mem_countbuckets, 16, "No of buckets for histogram");EXTERN INT_VAR (mem_checkfreq, 0, "Calls to alloc_mem between owner counts");/********************************************************************** * MEM_ALLOCATOR::MEM_ALLOCATOR * * Constructor for a memory allocator. **********************************************************************/voidMEM_ALLOCATOR::init ( //initializevoid *(*ext_malloc) (INT32), //external sourcevoid (*ext_free) (void *), //external freeINT32 firstsize, //size of first blockINT32 lastsize, //size of last blockINT32 maxchunk //biggest request) { blockcount = 0; malloc_serial = 0; topblock = NULL; currblock = NULL; callers = NULL; malloc = ext_malloc; free = ext_free; maxsize = lastsize; biggestblock = maxchunk; totalmem = 0; memsize = firstsize; malloc_div_ratio = 1; malloc_minor_serial = 0; malloc_auto_count = 0; call_bits = 0; entries = 0;}/********************************************************************** * MEM_ALLOCATOR::hash_caller * * Generate a hash code for a caller, setup the tables if necessary. **********************************************************************/UINT16 MEM_ALLOCATOR::hash_caller( //get hash code void *addr //return address ) { INT32 index; //index to table INT32 initial_hash; //initial index if (callers == NULL) init_callers(); //setup table //get hash code initial_hash = hash (call_bits, &addr, sizeof (addr)); if (initial_hash == 0) initial_hash = 1; index = initial_hash; if (callers[index].caller != NULL && callers[index].caller != addr) { do { index++; if (index >= entries) index = 1; } while (callers[index].caller != NULL && callers[index].caller != addr && index != initial_hash); if (index == initial_hash) index = 0; } if (callers[index].caller == NULL) { if (index != 0) callers[index].caller = addr; if (callers[index].free_list == NULL) //setup free table callers[index].init_freeers (); } return (UINT16) index;}/********************************************************************** * MALLOC_CALL::count_freeer * * Generate a hash code for a freeer, setup the tables if necessary. * Then count the call. **********************************************************************/void MALLOC_CALL::count_freeer( //count calls to free void *addr //return address ) { INT32 entries; //entries in table INT32 index; //index to table INT32 initial_hash; //initial index if (free_list == NULL) init_freeers(); //setup table entries = 1 << free_bits; //get hash code initial_hash = hash (free_bits, &addr, sizeof (addr)); if (initial_hash == 0) initial_hash = 1; index = initial_hash; if (free_list[index].freeer != NULL && free_list[index].freeer != addr) { do { index++; if (index >= entries) index = 1; } while (free_list[index].freeer != NULL && free_list[index].freeer != addr && index != initial_hash); if (index == initial_hash) index = 0; } if (free_list[index].freeer == NULL && index != 0) { free_list[index].freeer = addr; } free_list[index].count++; //count them}/********************************************************************** * MEM_ALLOCATOR::init_callers * * Initialize the callers hash table. **********************************************************************/void MEM_ALLOCATOR::init_callers() { //setup hash table INT32 depth = mem_mallocdepth; mem_mallocdepth.set_value (0); //can't register it call_bits = mem_mallocbits; entries = 1 << call_bits; //make an array callers = new MALLOC_CALL[entries]; mem_mallocdepth.set_value (depth);}/********************************************************************** * MALLOC_CALL::init_freeers * * Initialize the freeers hash table. **********************************************************************/void MALLOC_CALL::init_freeers() { //setup hash table INT32 entries; //entries in table INT32 depth = mem_mallocdepth; mem_mallocdepth.set_value (0); //can't register it free_bits = mem_freebits; entries = 1 << free_bits; //make an array free_list = new FREE_CALL[entries]; mem_mallocdepth.set_value (depth);}/********************************************************************** * MEM_ALLOCATOR::reduce_counts * * Divide all ages by 2 to get a log use of counts. **********************************************************************/void MEM_ALLOCATOR::reduce_counts() { //divide by 2 MEMBLOCK *block; //current block MEMUNION *chunk; //current chunk INT32 chunksize; //size of chunk INT32 blockindex; //index of block check_mem ("Reducing counts", JUSTCHECKS); for (blockindex = 0; blockindex < blockcount; blockindex++) { //current block block = &memblocks[blockindex]; //scan all chunks for (chunk = block->blockstart; chunk != block->blockend; chunk += chunksize) { chunksize = chunk->size; //size of chunk if (chunksize < 0) chunksize = -chunksize; //absolute size chunk->age /= 2; //divide ages } }}/********************************************************************** * MEM_ALLOCATOR::display_counts * * Send counts of outstanding blocks to stderr. **********************************************************************/void MEM_ALLOCATOR::display_counts() { //count up MEMBLOCK *block; //current block MEMUNION *chunk; //current chunk INT32 chunksize; //size of chunk INT32 blockindex; //index of block INT32 buckets; //required buckets INT32 bucketsize; //no in each bucket INT32 callindex; //index to callers INT32 freeindex; //index to freeers INT32 freeentries; //table size INT32 totalchunks; //total chunk counts INT32 totalspace; //total mem space INT32 totalpchunks; //permanent chunks INT32 totalpspace; //permanent space INT32 totalfrees; //total free calls if (callers == NULL) return; //can't do anything check_mem ("Displaying counts", JUSTCHECKS); buckets = mem_countbuckets; bucketsize = (malloc_serial - 1) / buckets + 1; tprintf ("\nEach bucket covers %g counts.\n", (double) bucketsize * malloc_div_ratio); for (callindex = 0; callindex < entries; callindex++) { if (callers[callindex].free_list != NULL) { callers[callindex].counts = (INT32 *) malloc (buckets * 4 * sizeof (INT32)); memset (callers[callindex].counts, 0, (size_t) (buckets * 4 * sizeof (INT32))); } } for (blockindex = 0; blockindex < blockcount; blockindex++) { //current block block = &memblocks[blockindex]; //scan all chunks for (chunk = block->blockstart; chunk != block->topchunk; chunk += chunksize) { chunksize = chunk->size; //size of chunk if (chunksize < 0) { chunksize = -chunksize; //absolute size callindex = chunk->owner; if (callers[callindex].counts != NULL) { callers[callindex].counts[chunk->age / bucketsize * 4]++; callers[callindex].counts[chunk->age / bucketsize * 4 + 1] += chunksize; } } } //scan all chunks for (; chunk != block->blockend; chunk += chunksize) { chunksize = chunk->size; //size of chunk if (chunksize < 0) { chunksize = -chunksize; //absolute size callindex = chunk->owner; if (callers[callindex].counts != NULL) { callers[callindex].counts[chunk->age / bucketsize * 4 + 2]++; callers[callindex].counts[chunk->age / bucketsize * 4 + 3] += chunksize; } } } } for (callindex = 0; callindex < entries; callindex++) { if (callers[callindex].counts != NULL) { for (totalspace = 0, totalchunks = 0, totalpspace = 0, totalpchunks = 0, freeindex = 0; freeindex < buckets; freeindex++) { totalchunks += callers[callindex].counts[freeindex * 4]; totalspace += callers[callindex].counts[freeindex * 4 + 1]; totalpchunks += callers[callindex].counts[freeindex * 4 + 2]; totalpspace += callers[callindex].counts[freeindex * 4 + 3]; } freeentries = 1 << callers[callindex].free_bits; for (totalfrees = 0, freeindex = 0; freeindex < freeentries; freeindex++) totalfrees += callers[callindex].free_list[freeindex].count; if (totalspace != 0 || totalfrees != 0) { tprintf ("alloc_mem at %d : total held=%d(%d), frees=%d.\n", callers[callindex].caller, totalchunks, totalspace * sizeof (MEMUNION), totalfrees); } if (totalspace > 0) { for (freeindex = 0; freeindex < buckets; freeindex++) { tprintf ("%d(%d) ", callers[callindex].counts[freeindex * 4], callers[callindex].counts[freeindex * 4 + 1] * sizeof (MEMUNION)); } tprintf ("\n"); } if (totalfrees != 0) { tprintf ("Calls to free : "); for (freeindex = 0; freeindex < freeentries; freeindex++) { if (callers[callindex].free_list[freeindex].count != 0) tprintf ("%d : %d ", callers[callindex].free_list[freeindex].freeer, callers[callindex].free_list[freeindex].count); } tprintf ("\n"); } if (totalpspace != 0) { tprintf ("alloc_mem_p at %d : total held=%d(%d).\n", callers[callindex].caller, totalpchunks, totalpspace * sizeof (MEMUNION)); for (freeindex = 0; freeindex < buckets; freeindex++) { tprintf ("%d(%d) ", callers[callindex].counts[freeindex * 4 + 2], callers[callindex].counts[freeindex * 4 + 3] * sizeof (MEMUNION));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -