140 likes | 244 Views
Finding Memory Leaks. The new operator and operator new. When allocating memory using new, e.g. Student *ps = new Student(“Yossi Cohen”); int *pi = new int[100]; The new operator (or new[] operator) is called The new ( new[] ) operator
E N D
The new operator and operator new • When allocating memory using new, e.g. • Student *ps = new Student(“Yossi Cohen”); • int *pi = new int[100]; The new operator (or new[] operator) is called • The new ( new[] ) operator • Calls operator new ( operator new[]) to allocate memory • Calls a constructor (default ctor, for arrays)
Overloading operator new • The newoperator cannot be overloaded • operator new and operator new[] can be overloaded in two ways: • For a given class • As global operators, which will apply for all types and classes for which these operators were not overloaded in the class. • When overloading operator new, one should also overload operator new[]. • operator new can be overloaded with extra parameters
The delete operator and operator delete • When releasing memory using delete, e.g. • Delete ps; • delete []pi; The delete operator (or delete[] operator) is called • The delete ( delete[] ) operator • Calls the destructor (destructors for arrays) • Calls operator delete ( operator delete[]) to release memory
Overloading operator delete • The deleteoperator cannot be overloaded • operator delete and operator delete[] can be overloaded in two ways: • For a given class • As global operators, which will apply for all types and classes for which these operators were not overloaded in the class. • When overloading operator delete, one should also overload operator delete[]. • operator delete can be overloaded with extra parameters
Overloading operator new and operator delete • operator new and operator delete can be overloaded to keep track of all memory allocations in a program • In the following example the global versions of these operators are overloaded
// CatchMemoryLeak.h Created by Yosi Halakhmi, private consultant #ifndef CATCHMEMORYLEAK_H #define CATCHMEMORYLEAK_H #include <stdlib.h> void saveInStorage( unsigned long addr, unsigned long nBytes, const char *fname, unsigned long lnum); void removeFromStorage(unsigned long addr); void reportUnreleasedHeap(); #ifdef _DEBUG inline void * operator new( unsigned int size, const char *fileName, int line) { void *ptr = (void *)malloc(size); saveInStorage((unsigned long)ptr, size, fileName, line); return(ptr); } inline void * operator new[](unsigned int size, const char * fileName, int line) { void *ptr = (void *)malloc(size); saveInStorage((unsigned long)ptr, size, fileName, line); return(ptr); }
inline void operator delete(void* ptr) { removeFromStorage((unsigned long)ptr); free(ptr); } inline void operator delete[](void* ptr) { removeFromStorage((unsigned long)ptr); free(ptr); } #endif // _DEBUG #ifdef DEBUG_NEW // MFC macro #undef DEBUG_NEW #endif #ifdef _DEBUG #define new new(__FILE__, __LINE__) #endif #endif // CATCHMEMORYLEAK_H
// CatchMemoryLeak.cpp #include <iostream> #include <fstream> #include <map> #include <string> using namespace std; struct HeapInfo_s { string fileName; unsigned long lineNo; unsigned long adrInHeap; unsigned long nBytes; }; typedef map<unsigned long, HeapInfo_s* > heapStorage_t; heapStorage_t* heapStorage; // global variable is initialized to 0 void saveInStorage(unsigned long addr, unsigned long nBytes, const char* fileName, unsigned long lineNo) { HeapInfo_s* hInfo; if(!heapStorage) { heapStorage = new(heapStorage_t); } hInfo = new (HeapInfo_s); hInfo->adrInHeap = addr; hInfo->fileName = fileName; hInfo->lineNo = lineNo; hInfo->nBytes = nBytes; (*heapStorage)[addr] = hInfo; }
void removeFromStorage(unsigned long addr) { if( heapStorage) { heapStorage_t::iterator itor; itor = heapStorage->find(addr); if (itor != heapStorage->end() ) { heapStorage->erase((itor)); } } } void reportUnreleasedHeap() { ofstream ofs("Leaks.txt"); if( heapStorage) { heapStorage_t::iterator itor; for(itor = heapStorage->begin(); itor != heapStorage->end(); ++itor) { ofs << "File Name : " << (*itor).second->fileName << endl; ofs << "Line No : " << (*itor).second->lineNo << endl; ofs << "Number of unreleased bytes : " << (*itor).second->nBytes << endl; ofs << endl; } } }
// TestMemoryLeak.cpp #include <iostream> #include "CatchMemoryLeak.h" using namespace std; class X{ charc; int y; public: X(char a=0, int b=0):c(a),y(b){} }; void func() { float* pf = new float; // memory leak } int main() { char* ip = new char; int* ip1 = new int[100]; int* ip2 = (int*)malloc(50*sizeof(int)); X* px=new X(‘a’,1); // memory leak func(); delete ip; delete []ip1; reportUnreleasedHeap(); return 0; }
Report: File Name : testmemoryleak.cpp Line No : 23 Number of unreleased bytes : 8 File Name : testmemoryleak.cpp Line No : 15 Number of unreleased bytes : 4 Alignment of int
Discussion • How can we keep track of possible deletions of already freed memory? • How can we keep track of overwriting data below or above the allocated block?