Introduction
In market, there are a lot of tools for detecting the memory leaks.
Here I made a program which has to include in your source file and it
will tell the desired informations to find where memory leaks happen.
There are two files one is findLeak.c and other is findLeak.h . Source
file is test.c , this is your program which you want to check memory
leaks.
Concept is that when user call library function "malloc or calloc " for
allocating dynamic memory, then we have to call our malloc or calloc
(In case of my source code 'MyCalloc' function in place of 'calloc' and
MyMalloc function in place of 'malloc'). So we have to define malloc to
your malloc and in .c file you have to undef malloc and calloc By this
way we can call our MyMalloc or MyCalloc function and in this function
we will call another function which keeps all info about how much
memory allocated. We will do the same for Library function "free" to
deallocating memory( In my source file "MyFree" is used in plae of free
function).
Using the code
Now for keeping information, i made a simple singly linked list. which
will add info about memory when user call "malloc" or "calloc" function
and will also keep information when user call "free" function.
By program you can easily understand.
Heder File : findLeak.h
#define uint unsigned int
#define cchar const char
#define OutFile "/home/asadulla/test/MemLeakInfo.txt" // Just Suppose
#define MAX_FILENAME_LENGTH 256
#define calloc(objs, nSize) MyCalloc (objs, nSize, __FILE__, __LINE__)
#define malloc(nSize) MyMalloc (nSize, __FILE__, __LINE__)
#define free(rMem) MyFree(rMem)
struct InfoMem
{
void *addr;
uint nSize;
char fileName[MAX_FILENAME_LENGTH];
uint lineNumber;
};
typedef struct InfoMem infoMem;
struct LeakMem
{
infoMem memData;
struct LeakMem *nxt;
};
typedef struct LeakMem leakMem;
void WriteMemLeak(void);
void SubAddMemInfo(void *rMem, uint nSize, cchar *file, uint lno);
void SubAdd(infoMem alloc_info);
void ResetInfo(uint pos);
void DeleteAll(void);
void *MyMalloc(uint size, cchar *file, uint line);
void *MyCalloc(uint elements, uint size, cchar * file, uint lno);
void MyFree(void * mem_ref);
Source File : findLeak.c
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include "findLeak.h"
#undef malloc
#undef calloc
#undef free
static leakMem * ptr_start = NULL;
static leakMem * ptr_next = NULL;
void *MyMalloc (uint nSize, cchar* file, uint lineNumber)
{
void * ptr = malloc (nSize);
if (ptr != NULL)
{
SubAddMemInfo(ptr, nSize, file, lineNumber);
}
return ptr;
}
void * MyCalloc (uint elements, uint nSize, const char * file, uint lineNumber)
{
uint tSize;
void * ptr = calloc(elements , nSize);
if(ptr != NULL)
{
tSize = elements * nSize;
SubAddMemInfo (ptr, tSize, file, lineNumber);
}
return ptr;
}
void SubAdd(infoMem alloc_info)
{
leakMem * mem_leak_info = NULL;
mem_leak_info = (leakMem *) malloc (sizeof(leakMem));
mem_leak_info->memData.addr = alloc_info.addr;
mem_leak_info->memData.nSize = alloc_info.nSize;
strcpy(mem_leak_info->memData.fileName, alloc_info.fileName);
mem_leak_info->memData.lineNumber = alloc_info.lineNumber;
mem_leak_info->nxt = NULL;
if (ptr_start == NULL)
{
ptr_start = mem_leak_info;
ptr_next = ptr_start;
}
else {
ptr_next->nxt = mem_leak_info;
ptr_next = ptr_next->nxt;
}
}
void ResetInfo(uint pos)
{
uint index = 0;
leakMem * alloc_info, * temp;
if(pos == 0)
{
leakMem * temp = ptr_start;
ptr_start = ptr_start->nxt;
free(temp);
}
else
{
for(index = 0, alloc_info = ptr_start; index < pos;
alloc_info = alloc_info->nxt, ++index)
{
if(pos == index + 1)
{
temp = alloc_info->nxt;
alloc_info->nxt = temp->nxt;
free(temp);
break;
}
}
}
}
void DeleteAll()
{
leakMem * temp = ptr_start;
leakMem * alloc_info = ptr_start;
while(alloc_info != NULL)
{
alloc_info = alloc_info->nxt;
free(temp);
temp = alloc_info;
}
}
void MyFree(void * mem_ref)
{
uint loop;
leakMem *leak_info = ptr_start;
for(loop = 0; leak_info != NULL; ++loop, leak_info = leak_info->nxt)
{
if ( leak_info->memData.addr == mem_ref )
{
ResetInfo(loop);
break;
}
}
free(mem_ref);
}
void SubAddMemInfo (void * mem_ref, uint nSize, cchar * file, uint lineNumber)
{
infoMem AllocInfo;
memset( &AllocInfo, 0, sizeof ( AllocInfo ) );
AllocInfo.addr = mem_ref;
AllocInfo.nSize = nSize;
strncpy(AllocInfo.fileName, file, MAX_FILENAME_LENGTH);
AllocInfo.lineNumber = lineNumber;
SubAdd(AllocInfo);
}
void WriteMemLeak(void)
{
uint index;
leakMem *leak_info;
FILE * fp_write = fopen(OutFile, "wt");
char info[1024];
if(fp_write != NULL)
{
sprintf(info, "%s\n", "SUMMARY ABOUT MEMORY LEAKS OF YOUR SOURCE FILE ");
fwrite(info, (strlen(info) + 1) , 1, fp_write);
sprintf(info, "%s\n", "-----------------------------------");
fwrite(info, (strlen(info) + 1) , 1, fp_write);
for(leak_info = ptr_start; leak_info != NULL; leak_info = leak_info->nxt)
{
sprintf(info, "Name of your Source File : %s\n", leak_info->memData.fileName);
fwrite(info, (strlen(info) + 1) , 1, fp_write);
sprintf(info, "Starting Address : %d\n", leak_info->memData.addr);
fwrite(info, (strlen(info) + 1) , 1, fp_write);
sprintf(info, " Total size Of memory Leak : %d bytes\n", leak_info->memData.nSize);
fwrite(info, (strlen(info) + 1) , 1, fp_write);
sprintf(info, "Line Number for which no DeAllocation : %d\n", leak_info->memData.lineNumber);
fwrite(info, (strlen(info) + 1) , 1, fp_write);
sprintf(info, "%s\n", "-----------------------------------");
fwrite(info, (strlen(info) + 1) , 1, fp_write);
fwrite(info, (strlen(info) + 1) , 1, fp_write);
}
}
DeleteAll();
}
These two files (header file and source file) user has to include in his source file to which user want to find memory leak.
Source File for detecting memory leak is as Here you can gice your
own source file and in this source file you have write onle line to
include file #include"findLeak.h"
Testing : test.c
Code: c
#include<malloc.h>
#include"findLeak.h"
int main()
{
int *p1 = (int *)malloc(10);
int *p2 = (int *)calloc(10, sizeof(int));
char *p3 = (char *) calloc(15, sizeof(float));
float *p4 = (float*) malloc(16);
free(p2);
WriteMemLeak();
return 0;
}
Now user can compile these programmes in a console as :
> g++ test.c findLeak.c
and give a command for run
> ./a.out
then go to you your directory where you have defined a macro "OutFile" and open this defined file and you can see the results.
Output of above source file is as:
Code: output
SUMMARY ABOUT MEMORY LEAKS OF YOUR SOURCE FILE
-----------------------------------
Name of your Source File : test.c
Starting Address : 184960
Total size Of memory Leak : 10 bytes
Line Number for which no DeAllocation : 7
-----------------------------------
-----------------------------------
Name of your Source File : test.c
Starting Address : 187104
Total size Of memory Leak : 60 bytes
Line Number for which no DeAllocation : 9
-----------------------------------
-----------------------------------
Name of your Source File : test.c
Starting Address : 184984
Total size Of memory Leak : 16 bytes
Line Number for which no DeAllocation : 10
-----------------------------------
-----------------------------------
Now you can try to make you own Test Cases just like test.c.