Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

operator new[] and non POD types

I'm trying to overload operator new in order to track memory allocations (For debugging). I'm having trouble when allocating arrays of non POD types (e.g. array of a class holding std::string).

It seems like operator new is called to allocate memory for the array + 8 bytes that are used to store the array length (probably so that the compiler can call the correct number of destructors when the array is destroyed).

How can operator new[] find out whether the actual data will be placed at the returned address (array of PODs) or at the returned address + 8? (I need this so that I can search structures for pointers)

like image 505
nimrodm Avatar asked Nov 10 '22 13:11

nimrodm


1 Answers

I presume it would do the same way that new[] knows what constructors to call: the compiler tells it. The compiler is keeping track of the data types and knows when it is a POD type or not.

But your real question is not how operator new[] knows or how the compiler knows but how can you find out.

If the object you are allocating is not size 8 then any size requested by new[] that isn't divisible by sizeof(object) would include the count of objects. That might work for you.

The following code sort of seems to work. I am sure there are plenty of ways to break it.

#include <new>
#include <iostream>

using namespace std;

class A {
    int x;
    int y;
};

class B {
    int x;
    int y;
    static int count;
public:
    B() : x(0), y(0) { ++count; }
    ~B() { --count; }
};

int B::count = 0;

template<class T>
T gcd(T a, T b)
{
    T tmp;
    while(b) {
        tmp = a % b;
        a = b;
        b = tmp;
    }
    return a;
}

void* operator new[](size_t count)
{
    size_t r = gcd(count, sizeof(size_t)*2);
    bool is_counted = r == sizeof(size_t);
    cout << count << " bytes requested and gcd is " << r << ' ' << (is_counted ? "is" : "is not") << " counted\n";
    return ::operator new[](count, std::nothrow);
}

int main()
{
    A* pa = new A[16];
    B* pb = new B[16];
    return 0;
}
like image 121
Zan Lynx Avatar answered Nov 14 '22 21:11

Zan Lynx