rendered paste body/* Interceptor memory management system
* Aaron Staley, cs61c-tg@imail.eecs.berkeley.edu
* Do NOT change anything in this file!
* We will be using our version of i_memory.c
* To the student: This is a fine example of when pointer casts are actually useful
* To the student: breaking at doMemCheck() will allow you to inspect the memory region
*/
#include "i_memory.h"
static int bytesUsed = 0;
static int numAlloc = 0;
typedef struct mem_info{
int line_num;
uint32_t size;
char * fname;
struct mem_info * next;
struct mem_info * prev;
} mem_info;
mem_info * head = NULL; //top of list
void add_block(mem_info * block){
block->next = head;
block->prev = NULL; //added 02/03
if (head) //arguably not needed
head->prev = block;
head = block;
}
void remove_block(mem_info * block){
if (block == head){
head = block->next;
if (head)
head->prev = NULL;
}
else{
if (block->next)
block->next->prev = block->prev;
block->prev->next = block->next;
}
}
void * iMalloc(size_t nbytes, char * fname, int line){
size_t allocReq = nbytes + sizeof(mem_info);
mem_info * block = malloc(allocReq);
if (!block){
fprintf(stderr,"MEM TESTER HAS RUN OUT OF MEMORY. YOU PROBABLY HAS A MEMORY LEAK!\n");
return 0;
}
block->line_num = line;
block->size = nbytes;
block->fname = fname;
add_block(block);
bytesUsed += nbytes;
numAlloc++;
return (void*)(block + 1);
}
/*dispatch malloc on this thing*/
void * iRealloc(void * ptr, size_t nbytes, char * fname, int line){
mem_info * block;
int oldSize;
void * nPtr;
if (!ptr)
return iMalloc(nbytes,fname,line);
if (nbytes == 0){
iFree(ptr,fname,line);
return 0;
}
block=((mem_info*)ptr) - 1;
oldSize = block->size;
nPtr = iMalloc(nbytes, fname,line);
memcpy(nPtr,ptr,oldSize>nbytes?nbytes:oldSize);
iFree(ptr,fname,line); //free old ptr
return nPtr;
}
void * iCalloc(size_t n, size_t s, char * fname, int line){ /*drive w/ malloc*/
void * data = iMalloc(s*n,fname,line);
memset(data,0,n*s);
return data;
}
void iFree(void * ptr, char * fname, int line){
mem_info * block;
if (!ptr)
return;
block=((mem_info*)ptr) - 1;
bytesUsed -= block->size;
remove_block(block);
numAlloc--;
free(block);
}
//memory checker
void doMemCheck(){
mem_info * block;
int i = 0;
if (!numAlloc){
fprintf(stdout,"Microscheme terminated. No memory leaks found\n");
return;
}
//error condition
fprintf(stderr,"Memory Leak detected on microscheme termination. %d outstanding allocations of %d bytes Total:\n",
numAlloc,bytesUsed);
//show all outstanding leaks
for (block = head; block != NULL; block = block->next, i++){
fprintf(stderr,"%d: %u bytes allocated at %s:%d\n",i,block->size,block->fname,block->line_num);
}
}
/*end malloc*/