#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
//non-NULL is the error code.
uint64_t* is_array_empty(uint64_t* addr, uint16_t addr_len)
{
uint64_t* addr_end;
addr_end = addr + addr_len;
do{
if(*addr != 0) return addr;
addr++;
}while(addr != addr_end);
return NULL;
}
//NULL is the error code.
uint64_t* is_in_array(uint64_t* addr, uint16_t addr_len, uint64_t point)
{
uint64_t* addr_end;
addr_end = addr + addr_len;
do{
if(*addr == point) return addr;
addr++;
}while(addr != addr_end);
return NULL;
}
uint64_t* add_to_array(uint64_t* addr, uint16_t* addr_len, uint64_t data)
{
uint64_t* addr_ret;
uint64_t* addr_new;
addr_ret = is_in_array(addr,*addr_len,data);//see if already in array
if(addr_ret != NULL)
{
printf("The newly allocated address %lx is already in array\n",data);
return NULL;
}
addr_ret = is_in_array(addr,*addr_len,0);//look for empty slot.
if(addr_ret == NULL)
{
(*addr_len)++;
addr_new = (uint64_t*)realloc(addr,(*addr_len)*sizeof(uint64_t));
if(addr_new == NULL)
{
puts("Unable to reallocate main array.");
return NULL;
}
addr_new[*addr_len-1] = data;
}
else
{
addr_new = addr;
*addr_ret = data;
}
return addr_new;
}
//one is error.
uint8_t replace_in_array(uint64_t* addr, uint16_t addr_len, uint64_t New, uint64_t old)
{
uint64_t* addr_tmp;
addr_tmp = is_in_array(addr,addr_len,old);
if(addr_tmp == NULL)//not in array
{
puts("old address is not allocated.");
return 1;
}
*addr_tmp = New;
return 0;
}
//one is the error code.
uint8_t del_from_array(uint64_t* addr, uint16_t addr_len, uint64_t data)
{
uint64_t* addr_ret;
addr_ret = is_in_array(addr,addr_len,data);
if(addr_ret == NULL)
{
puts("The address freed was not allocated.");
return 1;
}
*addr_ret = 0;
return 0;
}
void print_array(uint64_t* addr,uint16_t addr_len)
{
uint64_t* addr_end;
addr_end = addr + addr_len;
for(;addr<addr_end;addr++)
{
printf("%p contains %lx\n",addr,*addr);
}
return;
}
//this function counts how many lines are in
//the file and the maximum number of character
//per line
//error code if zero
uint32_t line_counter(FILE* fp,uint8_t* char_count_max)
{
uint16_t line_count;
uint16_t char_read,ii;
uint16_t char_count;
char *buf;
buf = calloc(4096,sizeof(char));
if(buf == NULL)
{
puts("Unable to allocate memory.");
return 0;
}
line_count = 0;
char_read = 0;
char_count = 0;
*char_count_max = 0;
ii=0;
do{
//if buffer is exhausted.
if(ii == char_read)
{
char_read = fread(buf,1,4096,fp);
if(char_read == 0) goto END;
ii=0;
}
if((buf[ii]<43) || (buf[ii]>122))
{
line_count++;
if(char_count > *char_count_max)
{
if(char_count > UINT8_MAX)
{
line_count= 0;
goto END;
}
*char_count_max = (uint8_t)char_count;
}
char_count=0;
}
else char_count++;
ii++;
}while(line_count!=UINT32_MAX);
END:
free(buf);
rewind(fp);
return line_count;
}
int main(void)
{
FILE* fp;
uint64_t* addr;
uint64_t* tmp;
uint64_t pointer0,pointer1;
uint16_t line_count,addr_len,ii;
uint8_t char_line_max;
char op;
fp = fopen("mem_check.log","r");
if(fp==NULL)
{
puts("Unable to open mem_check.log");
return -1;
}
line_count = line_counter(fp,&char_line_max);
if(line_count == 0)
{
puts("There was an error with the file format.");
fclose(fp);
return -1;
}
addr_len = (line_count>>2)+ 1;//divide by four and add 1.
addr = (uint64_t*)calloc(sizeof(uint64_t),addr_len);
if(addr == NULL)
{
puts("Unable to allocate memory");
fclose(fp);
return -1;
}
ii = 0;
do{
if(fscanf(fp,"%c%lx,%lx\n",&op,&pointer0,&pointer1) == EOF) break;
//printf("%c%lx,%lx\n",op,pointer0,pointer1);
if(op == 'a')
{
addr = add_to_array(addr,&addr_len,pointer0);
if(addr == NULL)
{
ERROR:
fclose(fp);
return -1;
}
//print_array(addr,addr_len);
//putchar('\n');
}
else if(op == 'f')
{
if(del_from_array(addr,addr_len,pointer0))
{
free(addr);
goto ERROR;
}
//print_array(addr,addr_len);
//putchar('\n');
}
else if(op == 'r')
{
if(replace_in_array(addr,addr_len,pointer1,pointer0))
{
free(addr);
goto ERROR;
}
//print_array(addr,addr_len)
}
else if(op == '\n') break;
else
{
printf("corrupted mem.log: op = %d\n",op);
free(addr);
goto ERROR;
}
}while(ii != line_count);
tmp = is_array_empty(addr,addr_len);
if(tmp == NULL) puts("There are no detected memory leaks");
else printf("%p not freed\n",tmp);
free(addr);
fclose(fp);
return 0;
}