How to detect memory leaks in C++

The original article of this in Japanese was written in 2007, so the content may be outdated and unusable.

A memory leak occurred in a project that use C++ on Linux.
I tried to use MemProfmtraceccmallocmpatrol、and dmalloc, but only mtrace was available in the project environment.

However, in the case of new/delete, the existence of the leak was confirmed, but the source file name and line number were not output (in the case of malloc/free, even the line number is output). It seems that dmalloc can be used with c++ new/delete, but when I tried to link it with the target program, I got a link error and cannot use it.

After looking up the relevant information, I had no choice, so I tried to write the code myself.

The codes override or overload new, new[], delete, delete[], and check the correspondence at the time of memory allocation and release. If memory has been allocated but not released, the file name and line number on the source that allocated the memory are displayed.
1. Copy DetectMemoryLeaks.h and DetectMemoryLeaks.cpp to your project.
2. Add DetectMemoryLeaks.cpp to the target of compile.
3. Add the following codes at top of source code file which be compiled at first.
    #include “MemoryLeakChecker.h”
    #define new new(__FILE__, __LINE__ )
4. Add the following code at the start of the range where you want to check for memory leaks.
    memoryLeakCheckerCheckStart(std::cout);
5. Add the following code at the end of the range where you want to check for memory leaks.
    memoryLeakCheckerCheckEnd(std::cout);
6. Compile your codes, and run it.
Example to use.(MemoryLeaksSample.cpp)。
Note: Multithreading is not considered, nesting of the detectMemoryLeaksStart/End call is not considered.

DetectMemoryLeaks.cpp

std::map detectMemoryLeaksMemoryMap;
bool detectMemoryLeaksFlag = false;

void *
operator new(std::size_t size, char * pszFileName, int nLineNum)
throw (std::bad_alloc)
{
void * address = malloc(size);
if(address == 0)
throw std::bad_alloc();

if(detectMemoryLeaksFlag){
// std::cout << “new: ” << pszFileName << “:” << nLineNum << ” size=” << size << ” address=” << address << std::endl;
std::ostringstream oss;
oss << pszFileName << “:” << nLineNum << ” size=” << size  << ” address=” << address;
detectMemoryLeaksMemoryMap.insert( std::pair((std::size_t)address, oss.str()) );
}
return address;
}

void *
operator new[](std::size_t size, char * pszFileName, int nLineNum)
throw (std::bad_alloc)
{
void * address = malloc(size);
if(address == 0)
throw std::bad_alloc();

if(detectMemoryLeaksFlag){
// std::cout << “new[]: ” << pszFileName << “:” << nLineNum << ” size=” << size << ” address=” << address << std::endl;
std::ostringstream oss;
oss << pszFileName << “:” << nLineNum << ” size=” << size  << ” address=” << address;
detectMemoryLeaksMemoryMap.insert( std::pair((std::size_t)address, oss.str()) );
}
return address;
}

void
operator delete(void * address)
{
if(address == 0) // Depends on environment.
return;

if(detectMemoryLeaksFlag){
// std::cout << “delete: ” << ” address=” << address << std::endl;
std::map::iterator it = detectMemoryLeaksMemoryMap.begin();
std::map::iterator itEnd = detectMemoryLeaksMemoryMap.end();
std::size_t checkAddress = (std::size_t)address;
for(; it!=itEnd; it++){
if(it->first == checkAddress){
detectMemoryLeaksMemoryMap.erase(it);
break;
}
}
}
free(address);
}

void
operator delete[](void * address)
{
if(address == 0) // Depends on environment.
return;

if(detectMemoryLeaksFlag){
// std::cout << “delete[]: ” << ” address=” << address << std::endl;
std::map::iterator it = detectMemoryLeaksMemoryMap.begin();
std::map::iterator itEnd = detectMemoryLeaksMemoryMap.end();
std::size_t checkAddress = (std::size_t)address;
for(; it!=itEnd; it++){
if(it->first == checkAddress){
detectMemoryLeaksMemoryMap.erase(it);
break;
}
}
}
fr
ee(address);
}

void
detectMemoryLeaksStart(std::ostream& ros)
{
ros << “[detect memory leaks] start” << std::endl;
detectMemoryLeaksFlag = true;
}

void
detectMemoryLeaksEnd(std::ostream& ros)
{
ros << “[detect memory leaks] end” << std::endl;
if(detectMemoryLeaksMemoryMap.size() > 0){
ros << “memory leaks …” << std::endl;
std::map::iterator it = detectMemoryLeaksMemoryMap.begin();
std::map::iterator itEnd = detectMemoryLeaksMemoryMap.end();
for(; it!=itEnd; it++)
ros << ”  ” << it->second << std::endl;
}else{
ros << “memory leak is nothing.” << std::endl;
}
detectMemoryLeaksFlag = false;
detectMemoryLeaksMemoryMap.clear();
}

Leave a Reply

Your email address will not be published. Required fields are marked *