Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to get total allocated size in custom operator delete[]?

I understand we can use Class-specific overloads of operator new[]/delete[] to specify our own memory allocation strategy.

So I write the following code. I barely want to use the held field to record how much memory of a type X<id> is allocated on heap.

However, I meet the problem that in operator new[], I can get the count, while I can’t in operator delete[]. So in operator delete[], I don’t know how much memory is actually released.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

#include <cstdio>
#include <string>
#include <vector>

template <int Id>
struct X {
    static inline int held = 0;
    static void* operator new(std::size_t count)
    {
        held += count;
        return ::operator new(count);
    }
 
    static void* operator new[](std::size_t count)
    {
        held += count;
        return ::operator new[](count);
    }

    static void operator delete(void* ptr)
    {
        held -= sizeof(X<Id>);
        ::operator delete(ptr);
    }

    static void operator delete[] (void* ptr)
    {
        // This is not correct.
        // However, I don't know the count.
        held -= sizeof(X<Id>);
        ::operator delete [] (ptr);
    }

    std::string s1;
    std::vector<int> v1;
};

int main() {
    auto * dx2 = new X<1>[100]();
    printf("x1d2 %d\n", X<1>::held);
    delete [] dx2;
    printf("x1d2 released %d\n", X<1>::held); // exptected 0
}

I understand one way is that I can allocate an extra bytes to store the count, it introduces extra overhead though.

Moreover, the compiler will actually store the count somewhere when compiling operator delete [], however, it is not exposed to users. I think I am now allowed to access the count.

>Solution :

Since C++14, there are flavors of operator delete (number (5)) and operator delete[] (number (6)), that you can override and have an additional parameter for the allocated size:

void operator delete ( void* ptr, std::size_t sz ) noexcept; (5)
void operator delete[] ( void* ptr, std::size_t sz ) noexcept; (6)

These operators have priority over the ones without the size:

Called instead of (1,2) if a user-defined replacement is provided,

In your case you can replace your operator delete and operator delete[] with:

static void operator delete(void* ptr, std::size_t sz)
{
    held -= sz;
    ::operator delete(ptr);
}

static void operator delete[](void* ptr, std::size_t sz)
{
    held -= sz;
    ::operator delete[](ptr);
}

Output on MSVC (last value is 0 as expected):

x1d2 7208
x1d2 released 0

Live demo

Some notes:

  1. held should better be a size_t to match the type in the new and delete operators.
  2. My live demo is using std::cout instead of the less-recommnded C style printfs.
  3. In the live demo held has different values after the allocation in different compilers because the size of classes is implementation dependant (but it is always 0 after deallocation).
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading