blob: 937a00b27f34d938b1296be24d8b34371e5510d0 [file] [log] [blame]
#ifndef COUNT_NEW_HPP
#define COUNT_NEW_HPP
# include <cstdlib>
# include <cassert>
# include <new>
#if __has_feature(address_sanitizer) \
|| __has_feature(memory_sanitizer)
#define DISABLE_NEW_COUNT
#endif
class MemCounter
{
public:
// Make MemCounter super hard to accidentally construct or copy.
class MemCounterCtorArg_ {};
explicit MemCounter(MemCounterCtorArg_) {}
private:
MemCounter(MemCounter const &);
MemCounter & operator=(MemCounter const &);
public:
// All checks return true when disable_checking is enabled.
static const bool disable_checking;
int outstanding_new = 0;
int new_called = 0;
int delete_called = 0;
int last_new_size = 0;
int outstanding_array_new = 0;
int new_array_called = 0;
int delete_array_called = 0;
int last_new_array_size = 0;
public:
void newCalled(std::size_t s)
{
assert(s);
++new_called;
++outstanding_new;
last_new_size = s;
}
void deleteCalled(void * p)
{
assert(p);
--outstanding_new;
++delete_called;
}
void newArrayCalled(std::size_t s)
{
assert(s);
++outstanding_array_new;
++new_array_called;
last_new_array_size = s;
}
void deleteArrayCalled(void * p)
{
assert(p);
--outstanding_array_new;
++delete_array_called;
}
void reset()
{
outstanding_new = 0;
new_called = 0;
delete_called = 0;
last_new_size = 0;
outstanding_array_new = 0;
new_array_called = 0;
delete_array_called = 0;
last_new_array_size = 0;
}
public:
bool checkOutstandingNewEq(int n) const
{
return disable_checking || n == outstanding_new;
}
bool checkOutstandingNewNotEq(int n) const
{
return disable_checking || n != outstanding_new;
}
bool checkNewCalledEq(int n) const
{
return disable_checking || n == new_called;
}
bool checkNewCalledNotEq(int n) const
{
return disable_checking || n != new_called;
}
bool checkDeleteCalledEq(int n) const
{
return disable_checking || n == delete_called;
}
bool checkDeleteCalledNotEq(int n) const
{
return disable_checking || n != delete_called;
}
bool checkLastNewSizeEq(int n) const
{
return disable_checking || n == last_new_size;
}
bool checkLastNewSizeNotEq(int n) const
{
return disable_checking || n != last_new_size;
}
bool checkOutstandingArrayNewEq(int n) const
{
return disable_checking || n == outstanding_array_new;
}
bool checkOutstandingArrayNewNotEq(int n) const
{
return disable_checking || n != outstanding_array_new;
}
bool checkNewArrayCalledEq(int n) const
{
return disable_checking || n == new_array_called;
}
bool checkNewArrayCalledNotEq(int n) const
{
return disable_checking || n != new_array_called;
}
bool checkDeleteArrayCalledEq(int n) const
{
return disable_checking || n == delete_array_called;
}
bool checkDeleteArrayCalledNotEq(int n) const
{
return disable_checking || n != delete_array_called;
}
bool checkLastNewArraySizeEq(int n) const
{
return disable_checking || n == last_new_array_size;
}
bool checkLastNewArraySizeNotEq(int n) const
{
return disable_checking || n != last_new_array_size;
}
};
#ifdef DISABLE_NEW_COUNT
const bool MemCounter::disable_checking = true;
#else
const bool MemCounter::disable_checking = false;
#endif
MemCounter globalMemCounter((MemCounter::MemCounterCtorArg_()));
#ifndef DISABLE_NEW_COUNT
void* operator new(std::size_t s) throw(std::bad_alloc)
{
globalMemCounter.newCalled(s);
return std::malloc(s);
}
void operator delete(void* p) throw()
{
globalMemCounter.deleteCalled(p);
std::free(p);
}
void* operator new[](std::size_t s) throw(std::bad_alloc)
{
globalMemCounter.newArrayCalled(s);
return operator new(s);
}
void operator delete[](void* p) throw()
{
globalMemCounter.deleteArrayCalled(p);
operator delete(p);
}
#endif // DISABLE_NEW_COUNT
#endif /* COUNT_NEW_HPP */