Finding Memory Leaks. The new operator and operator new When allocating memory using new, e.g....
-
Upload
beryl-glenn -
Category
Documents
-
view
216 -
download
4
Transcript of Finding Memory Leaks. The new operator and operator new When allocating memory using new, e.g....
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– Calls operator new ( operator new[]) to
allocate memory– Calls a constructor (default ctor, for arrays)
Overloading operator new
• The new operator 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 delete operator 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 {char c;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;
}
File Name : testmemoryleak.cppLine No : 23Number of unreleased bytes : 8
File Name : testmemoryleak.cppLine No : 15Number of unreleased bytes : 4
Report:
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?