|
Background
This article explains about how to detect memory leaks in C/C++ programming
for the memory allocated using the functions malloc, strdup and calloc. There
are commercially available tools which will have more advance features. The code
snipped explained in this article will explain a simple way to detect memory
leaks for malloc, strdup and calloc function. With the following code I have
successfully detected most of memory leaks I have tested the following code in unix, linux and windows
environment. Call DisplayMallocDetails to know the memory leaks. Use this
software only in small applications.
//malloc_h.h
/****************************************************************************************
Header declaration
****************************************************************************************/
#ifndef _MALLOC_H
#define _MALLOC_H
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#ifdef MALLOC
#define malloc(size) ___malloc((size),(__LINE__),__FILE__)
#define realloc(addr,size) ___realloc((addr),(size),(__LINE__),(__FILE__))
#define strdup(str) ___strdup((str),(__LINE__),(__FILE__))
#define free(str) ___free(str)
#endif
#ifdef __cplusplus
extern "C" {
#endif
void* ___malloc(size_t size,int line,char file[255]);
void* ___realloc(void* addr, size_t size, int line, char file[255]);
void ___free(void* mem);
void* ___strdup(char* str,int size, char file[255]);
void DisplayLeakDetails();
#ifdef __cplusplus
}
#endif
typedef struct MALLOCDETAILS
{
char file[255];
int line;
int size;
long addr;
struct MALLOCDETAILS *nextout;
}MALLOCDETAILS;
#endif
/************* END OF FILE ***************/
////malloc_h.cpp
/*******************************************************************************************
Function declarations
********************************************************************************************/
#include "malloc_h.h"
int mallocIndex = 0;
int mallocCount = 0;
MALLOCDETAILS *mainNode = NULL;
void addNode(int line,long addr, int size,char file[255]);
void deleteNode(long addr);
MALLOCDETAILS* getNode(long addr);
void* ___realloc(void* addr,size_t size,int line, char file[255]);
void* ___malloc(size_t size,int line, char file[255])
{
void *addr = NULL;
addr = (void*)malloc(size);
if(addr == NULL)
{
return addr;
}
addNode(line,(long)addr,size,file);
return addr;
}
|
|
void* ___strdup(char* str,int line, char file[255])
{
void *addr = NULL;
addr = strdup(str);
if(addr == NULL)
{
return addr;
}
addNode(line,(long)addr,strlen(str),file);
return addr;
}
void* ___realloc(void* addr,size_t size,int line, char file[255])
{
MALLOCDETAILS *mdetails = getNode((long)addr);
addr = (void*)realloc(addr,size);
if(addr == NULL)
{
return addr;
}
mdetails->addr = (long)addr;
mdetails->line = line;
strcpy(mdetails->file,file);
mdetails->size = size;
return addr;
}
void ___free(void* mem)
{
deleteNode((long)mem);
free(mem);
}
/*addNode will add the memory in the linked list. It will last in the linked
list until it is freed from the memory*/
void addNode(int line,long addr, int size,char file[255])
{
MALLOCDETAILS *tempnode = mainNode;
if(mainNode == NULL)
{
mainNode = (MALLOCDETAILS*)malloc(sizeof(MALLOCDETAILS));
mainNode->nextout = NULL;
mainNode->line = line;
mainNode->addr = addr;
mainNode->size = size;
strcpy(mainNode->file,file);
}
else
{
while(tempnode->nextout != NULL) tempnode = tempnode->nextout;
tempnode->nextout = (MALLOCDETAILS*)malloc(sizeof(MALLOCDETAILS));
tempnode->nextout->nextout = NULL;
tempnode->nextout->line = line;
tempnode->nextout->addr = addr;
tempnode->nextout->size = size;
strcpy(mainNode->nextout->file,file);
}
}
/*deleteNode method will delete the allocated memory from the linked list.
Because it is freed from the momory*/
void deleteNode(long addr)
{
MALLOCDETAILS *t1=NULL,*tempnode = mainNode;
if(mainNode->addr == addr)
{
mainNode = mainNode->nextout;
free(tempnode);
return;
}
while(tempnode->nextout != NULL)
{
if(tempnode->nextout->addr != addr)
{
tempnode = tempnode->nextout;
continue;
}
else
{
t1 = tempnode->nextout;
tempnode->nextout = tempnode->nextout->nextout;
free(t1);
}
}
}
MALLOCDETAILS* getNode(long addr)
{
MALLOCDETAILS *tempnode = mainNode;
while(tempnode!= NULL)
{
if(tempnode->addr != addr)
{
tempnode = tempnode->nextout;
continue;
}
else
{
return tempnode;
}
}
return NULL;
}
/* DisplayLeakDetails function can be called to check the memory leaks, it will
write all the memory leaks found into a
malloc_leaks.dat file.
*/
void DisplayLeakDetails()
{
FILE *fp;
int i=0;
unsigned long leakedBlocks = 0;
MALLOCDETAILS *tempnode = mainNode;
fp = fopen("malloc_leaks.dat","a+");
while(tempnode != NULL)
{
fprintf(fp,"File: %s Line: %d size: %d addr %d\n",
tempnode->file,tempnode->line, tempnode->size,
tempnode->addr);
leakedBlocks += tempnode->size;
tempnode = tempnode->nextout;
}
fprintf(fp,"total leaked bytes are %u\n",leakedBlocks);
fclose(fp);
}
/************** END OF FILE **************/
|
|
Unix/Linux environment
To use the above code, create the library libmalloc.a in unix/linux
environment
Include the file malloc_h.h in the test program
#include<stdio.h>
#include "malloc_h.h"
void main()
{
char* a = (char*)malloc(100);
char *b = "sldfl";
char* d = (char*)strdup(b);
char *e = (char*)malloc(200);
strcpy(e,"lklkjk");
e = (char*)realloc(e,250);
free(a);
DisplayLeakDetails();
}
Windows environment
Open a new project and select static library option, include the files
malloc_h.h and malloc_h.cpp and create the static library malloc.lib.
Create another SDI project and in OnDraw method insert the following
statements.
char* a = (char*)malloc(100);
char *b = "sldfl";
char* d = (char*)strdup(b);
char *e = (char*)malloc(200);
strcpy(e,"lklkjk");
e = (char*)realloc(e,250);
free(a);
Add WM_DESTROY message handler in the view and call DisplayLeakDetails();
When you run and exit from the software, it will create malloc_leaks.dat and the
result will be
File: D:\software\malloc\mallocView.cpp Line: 62 size: 5 addr 18753968
File: D:\software\malloc\mallocView.cpp Line: 65 size: 250 addr 18752768
total leaked bytes are 255
|