0

I am trying to find out the total memory allocated and later freed by my program to figure out if there are any memory leaks by overloading the new and delete operators. Below are the overloaded methods of new and delete:

void* operator new(size_t sz)
{
    void* m = (void*) MemoryManager::getInstance()->allocate(sz, false);
    if(!m){
        throw std::bad_alloc{};
    }
    return m;
}

// Overloading Global delete operator
void operator delete(void* m) noexcept
{
    MemoryManager::getInstance()->deallocate(m, false);
}

The allocate and deallocate methods that new and delete are calling are defined as below:

PointerType allocate(size_t size, bool isArray){
    PointerType newPtr = (PointerType)std::malloc(size);
    mMemKeeper[newPtr] = size;
    mBytes += size;
    return newPtr;
}

void  MemoryManager::deallocate(void* pt, bool isArray){
    LockGuard lck(mGateKeeper);
    if(mMemKeeper.find((PointerType)pt) != mMemKeeper.end()){
        mBytes -= mMemKeeper[(PointerType)pt];
        mMemKeeper.erase((PointerType)pt);
        std::free(pt);
    }
}

typedef char*                                                 PointerType;
typedef std::unordered_map<PointerType, MemoryInfo,
std::hash<PointerType>, std::equal_to<PointerType>,
my_allocator<std::pair<const PointerType, MemoryInfo> > >     OrderedMap;
OrderedMap                                                    mMemKeeper;

The issue I am facing is in deallocate while accessing mMemKeeper.find((PointerType)pt). Seems like the pointer pt is already deallocated by the time it reaches here and dereferencing it is causing problems. When can this happen and is there a way I can detect if memory of pt is already freed?

Jarod42
  • 203,559
  • 14
  • 181
  • 302
Bharath
  • 171
  • 1
  • 15
  • I tried accessing the memory location of the pointer when this issue occurred from Visual Studio and it shows 00 00 00 00 00 00 which I assume means that the memory has been freed already – Bharath Mar 22 '21 at 14:48
  • ***I assume means that the memory has been freed already*** No Visual Studio has a different code for that. Related: [https://stackoverflow.com/questions/127386/in-visual-studio-c-what-are-the-memory-allocation-representations](https://stackoverflow.com/questions/127386/in-visual-studio-c-what-are-the-memory-allocation-representations) – drescherjm Mar 22 '21 at 14:49
  • 6
    Consider not doing this unless you do it for sport/fun/learning. There are already multiple specialized tools for purpose of detecting memory leaks – bartop Mar 22 '21 at 14:50
  • 1
    Can you provide a [mcve]? Also, your `deallocate` function is searching the map *three times*! 1. `mMemKeeper.find(...)` 2. `mMemKeeper[...]` 3. `mMemKeeper.erase(...)`. Do something like 1. `auto it = mMemKeeper.find(...)` 2. `it->second` 3. `mMemKeeper.erase(it)` instead. – Kevin Mar 22 '21 at 14:52
  • `mMemKeeper.find((PointerType)pt)` doesn't dereference the pointer – user253751 Mar 22 '21 at 14:52
  • 1
    You can always allocate an extra space before and after your buffer and put a magic number in them Useful for detecting overruns too. – doug Mar 22 '21 at 15:11

1 Answers1

0

Seems like the pointer pt is already deallocated by the time it reaches here and dereferencing it is causing problems.

Yes, double-freeing is a bug. The result of accessing free'd memory is undefined.

I tried accessing the memory location of the pointer when this issue occurred from Visual Studio and it shows 00 00 00 00 00 00 which I assume means that the memory has been freed already

If you dereference the pointer when it might be unallocated, you've already failed. The only safe way to determine whether a pointer is allocated, is to look it up elsewhere.

When can this happen

When you explicitly delete the same object more than once, or when you explicitly delete something already controlled by a smart pointer, or if you explicitly delete something that wasn't allocated with new in the first place.

and is there a way I can detect if memory of pt is already freed?

You sort of already are. If the address isn't in your container of allocated blocks, it either wasn't allocated from here in the first place, or was already released. You can add some explicit tracking for double-freeing if you need to: just add another container.

I am trying to find out the total memory allocated and later freed by my program to figure out if there are any memory leaks

If this is just for your own interest/learning, that's fine. Otherwise you're missing a lot of features, and should just use your compiler's address sanitizer if it has one, or valgrind if not.

Useless
  • 64,155
  • 6
  • 88
  • 132