Thread: To find the memory leaks without using any tools

  1. #1
    Registered User
    Join Date
    Mar 2008
    Posts
    2

    To find the memory leaks without using any tools

    I worked for a long time for this article. This program is tested on Sun-Solaris system using gcc compiler.

    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).

    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

    Code:
    #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)
    
    // This structure is keeping info about memory leak
    struct InfoMem
    {
    	void *addr;
    	uint nSize;
    	char fileName[MAX_FILENAME_LENGTH];
    	uint lineNumber;
    };
    typedef struct InfoMem infoMem;
    
    //This is link list of InfoMem which keeps a List of memory Leak in a source file
    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); //erase
    void DeleteAll(void); //clear(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

    Code:
    #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;
    
    
    
    
    // -----------------------------------------------------------
    // Name: MyMalloc
    // Desc: This is hidden to user. when user call malloc function then 
    //       this function will be called.
    
    
    void *MyMalloc (uint nSize, cchar* file, uint lineNumber)
    {
    	void * ptr = malloc (nSize);
    	if (ptr != NULL) 
    	{
    		SubAddMemInfo(ptr, nSize, file, lineNumber);
    	}
    	return ptr;
    }
    
    // -----------------------------------------------------------
    // Name: MyCalloc
    // Desc: This is hidden to user. when user call calloc function then 
    //       this function will be called.
    
    
    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;
    }
    
    // -----------------------------------------------------------
    // Name: SubAdd
    // Desc: It's actually  Adding the Info.
    
    
    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;				
    	}
    
    }
    
    
    
    // -----------------------------------------------------------
    // Name: ResetInfo
    // Desc: It erasing the memory using by List on the basis of info( pos)
    
    
    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;
    			}
    		}
    	}
    }
    
    // -----------------------------------------------------------
    // Name: DeleteAll
    // Desc: It deletes the all elements which resides on List
    
    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;
    	}
    }
    
    
    // -----------------------------------------------------------
    // Name: MyFree
    // Desc: 
    
    
    void MyFree(void * mem_ref)
    {
    		uint loop;
       // if the allocated memory info is part of the list, removes it
    	leakMem  *leak_info = ptr_start;
    	/* check if allocate memory is in our list */
    	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);
    }
    
    
    // -----------------------------------------------------------
    // Name: SubAddMemInfo
    // Desc: it also fill the the Info
    
    
    void SubAddMemInfo (void * mem_ref, uint nSize, cchar * file, uint lineNumber)
    {
    	infoMem AllocInfo;
    
    	/* fill up the structure with all info */
    	memset( &AllocInfo, 0, sizeof ( AllocInfo ) );
    	AllocInfo.addr 	= mem_ref;
    	AllocInfo.nSize = nSize;
    	strncpy(AllocInfo.fileName, file, MAX_FILENAME_LENGTH);
    	AllocInfo.lineNumber = lineNumber;
    	
    	/* SubAdd the above info to a list */
    	SubAdd(AllocInfo);
    }
    
    // -----------------------------------------------------------
    // Name: WriteMemLeak
    // Desc: It writes information about Memory leaks in a file 
    //       Example: File is as : "/home/asadulla/test/MemLeakInfo.txt"
    
    
    
    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.

    Test 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"


    Test Source File : test.c

    Code:
    #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:
    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
    -----------------------------------
    -----------------------------------

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    A few comments:
    Code:
    // This structure is keeping info about memory leak
    struct InfoMem
    {
    	void *addr;
    	uint nSize;
    	char fileName[MAX_FILENAME_LENGTH];
    	uint lineNumber;
    };
    typedef struct InfoMem infoMem;
    
    //This is link list of InfoMem which keeps a List of memory Leak in a source file
    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); //erase
    void DeleteAll(void); //clear(void);
    should never be needed outside your .c file, so no need to put it in the header file.

    Code:
    void SubAddMemInfo (void * mem_ref, uint nSize, cchar * file, uint lineNumber)
    {
    	infoMem AllocInfo;
    
    	/* fill up the structure with all info */
    	memset( &AllocInfo, 0, sizeof ( AllocInfo ) );
    	AllocInfo.addr 	= mem_ref;
    	AllocInfo.nSize = nSize;
    	strncpy(AllocInfo.fileName, file, MAX_FILENAME_LENGTH);
    	AllocInfo.lineNumber = lineNumber;
    	
    	/* SubAdd the above info to a list */
    	SubAdd(AllocInfo);
    }
    If you change the filename into a pointer, you don't need to strcpy() the filename. Also, if you use strncpy, you should make sure the last char is 0.


    Code:
    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;				
    	}
    
    }
    Surely we could just have ONE function that does SubAdd and SubAddMemInfo, avoiding the second copying of the infoMem into leakMem.

    Is there any particular reason why you are using sprintf + fwrite instead of fprintf() in your reporting function?


    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Registered User
    Join Date
    Apr 2008
    Posts
    890
    Shouldn't this be in the C Programming forum?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Checking for memory leaks
    By Bladactania in forum C Programming
    Replies: 5
    Last Post: 02-10-2009, 12:58 PM
  2. memory leaks
    By TehOne in forum C Programming
    Replies: 4
    Last Post: 10-10-2008, 09:33 PM
  3. Memory leaks problem in C -- Help please
    By Amely in forum C Programming
    Replies: 14
    Last Post: 05-21-2008, 11:16 AM
  4. Memory leaks!!!
    By kaushik1986 in forum C++ Programming
    Replies: 2
    Last Post: 10-08-2007, 05:41 AM
  5. Memory Leaks
    By SwirlingVortex in forum C++ Programming
    Replies: 2
    Last Post: 09-21-2001, 06:34 AM