/* * set both the signatures for a chunk to a particular value * 'chunk' must be the index of the bottom signature for a chunk * NOTE: if you change the size of this chunk with this function * then we'll set the end signature for the NEW SIZE! */ void setBothSignatures(unsigned chunk, int value) { unsigned top; memory_pool[chunk] = value; top = topSignature(chunk); memory_pool[top] = value; }
void displayChunks(void) { int size; int num_chunks = 0; unsigned chunk = 0; int top_signature; while (chunk < pool_size) { num_chunks += 1; size = memory_pool[chunk]; printf("chunk %d ", num_chunks); top_signature = memory_pool[topSignature(chunk)]; if (size != top_signature) { printf(" has a signature mismatch problem! oh fudge\n"); exit(-1); } if (size > 0) { printf(" is available"); } else { printf(" is in use"); } if (size < 0) { size = -size; } printf(" and has %d words of available storage\n", size); chunk = successorChunk(chunk); } }
void deallocateMemory(void *p) { /* since the available memory is one position above the signature * the signature can be found at one position below the first * byte of available memory */ int *chunk_address = ((int *)p) - 1; unsigned chunk; int top_signature; int bottom_signature; int size; if ((chunk_address < memory_pool) || (chunk_address >= &memory_pool[pool_size])) { /* due to silliness in the MetroWerks compiler, it is possible * for new to be called before the memory heap is on-line. In that * case the system default heap is used, and not this one. * this generally only happens for global constructors, such as * the stuff associated with cout and cin. * When these objects are destroyed (after main ends) the * runtime system calls delete on all these things but * since our heap is now online, we get all the other heap's memory * back. We're just going to ignore it. The OS will clean up * that memory anyway when the application quits, so its * no big deal. */ /* if you want to see this in action, de-comment the following line */ // cout << "hey! that ain't mine, don't throw that junk at me\n"; return; } chunk = chunk_address - memory_pool; bottom_signature = memory_pool[chunk]; top_signature = memory_pool[topSignature(chunk)]; /* another sanity check, not really insane at all. */ assert(bottom_signature == top_signature && bottom_signature < 0); size = -bottom_signature; setBothSignatures(chunk, size); mergeChunkIfOK(chunk); if (chunk > 0) { // this is not quite silly, chunk could be equal to zero unsigned previous_chunk = predecessorChunk(chunk); mergeChunkIfOK(previous_chunk); } if (mem_leak_check && isEmptyHeap()) { std::cout << "Yay, you do not have a memory leak!" << std::endl; } }
/* * sanity check the heap and return true if it looks OK, * return false if something is messed up */ bool isSaneHeap(void) { unsigned chunk = 0; /* check each chunk to see if top and bottom sigs match */ while (chunk < pool_size) { if (memory_pool[chunk] != memory_pool[topSignature(chunk)]) { return false; } chunk = successorChunk(chunk); } return true; }