1*0a6a1f1dSLionel Sambuc #ifndef COUNT_NEW_HPP 2*0a6a1f1dSLionel Sambuc #define COUNT_NEW_HPP 3*0a6a1f1dSLionel Sambuc 4*0a6a1f1dSLionel Sambuc # include <cstdlib> 5*0a6a1f1dSLionel Sambuc # include <cassert> 6*0a6a1f1dSLionel Sambuc # include <new> 7*0a6a1f1dSLionel Sambuc 8*0a6a1f1dSLionel Sambuc #ifndef __has_feature 9*0a6a1f1dSLionel Sambuc # define __has_feature(x) 0 10*0a6a1f1dSLionel Sambuc #endif 11*0a6a1f1dSLionel Sambuc 12*0a6a1f1dSLionel Sambuc #if __has_feature(address_sanitizer) \ 13*0a6a1f1dSLionel Sambuc || __has_feature(memory_sanitizer) \ 14*0a6a1f1dSLionel Sambuc || __has_feature(thread_sanitizer) 15*0a6a1f1dSLionel Sambuc #define DISABLE_NEW_COUNT 16*0a6a1f1dSLionel Sambuc #endif 17*0a6a1f1dSLionel Sambuc 18*0a6a1f1dSLionel Sambuc class MemCounter 19*0a6a1f1dSLionel Sambuc { 20*0a6a1f1dSLionel Sambuc public: 21*0a6a1f1dSLionel Sambuc // Make MemCounter super hard to accidentally construct or copy. 22*0a6a1f1dSLionel Sambuc class MemCounterCtorArg_ {}; MemCounter(MemCounterCtorArg_)23*0a6a1f1dSLionel Sambuc explicit MemCounter(MemCounterCtorArg_) { reset(); } 24*0a6a1f1dSLionel Sambuc 25*0a6a1f1dSLionel Sambuc private: 26*0a6a1f1dSLionel Sambuc MemCounter(MemCounter const &); 27*0a6a1f1dSLionel Sambuc MemCounter & operator=(MemCounter const &); 28*0a6a1f1dSLionel Sambuc 29*0a6a1f1dSLionel Sambuc public: 30*0a6a1f1dSLionel Sambuc // All checks return true when disable_checking is enabled. 31*0a6a1f1dSLionel Sambuc static const bool disable_checking; 32*0a6a1f1dSLionel Sambuc 33*0a6a1f1dSLionel Sambuc // Disallow any allocations from occurring. Useful for testing that 34*0a6a1f1dSLionel Sambuc // code doesn't perform any allocations. 35*0a6a1f1dSLionel Sambuc bool disable_allocations; 36*0a6a1f1dSLionel Sambuc 37*0a6a1f1dSLionel Sambuc int outstanding_new; 38*0a6a1f1dSLionel Sambuc int new_called; 39*0a6a1f1dSLionel Sambuc int delete_called; 40*0a6a1f1dSLionel Sambuc int last_new_size; 41*0a6a1f1dSLionel Sambuc 42*0a6a1f1dSLionel Sambuc int outstanding_array_new; 43*0a6a1f1dSLionel Sambuc int new_array_called; 44*0a6a1f1dSLionel Sambuc int delete_array_called; 45*0a6a1f1dSLionel Sambuc int last_new_array_size; 46*0a6a1f1dSLionel Sambuc 47*0a6a1f1dSLionel Sambuc public: newCalled(std::size_t s)48*0a6a1f1dSLionel Sambuc void newCalled(std::size_t s) 49*0a6a1f1dSLionel Sambuc { 50*0a6a1f1dSLionel Sambuc assert(disable_allocations == false); 51*0a6a1f1dSLionel Sambuc assert(s); 52*0a6a1f1dSLionel Sambuc ++new_called; 53*0a6a1f1dSLionel Sambuc ++outstanding_new; 54*0a6a1f1dSLionel Sambuc last_new_size = s; 55*0a6a1f1dSLionel Sambuc } 56*0a6a1f1dSLionel Sambuc deleteCalled(void * p)57*0a6a1f1dSLionel Sambuc void deleteCalled(void * p) 58*0a6a1f1dSLionel Sambuc { 59*0a6a1f1dSLionel Sambuc assert(p); 60*0a6a1f1dSLionel Sambuc --outstanding_new; 61*0a6a1f1dSLionel Sambuc ++delete_called; 62*0a6a1f1dSLionel Sambuc } 63*0a6a1f1dSLionel Sambuc newArrayCalled(std::size_t s)64*0a6a1f1dSLionel Sambuc void newArrayCalled(std::size_t s) 65*0a6a1f1dSLionel Sambuc { 66*0a6a1f1dSLionel Sambuc assert(disable_allocations == false); 67*0a6a1f1dSLionel Sambuc assert(s); 68*0a6a1f1dSLionel Sambuc ++outstanding_array_new; 69*0a6a1f1dSLionel Sambuc ++new_array_called; 70*0a6a1f1dSLionel Sambuc last_new_array_size = s; 71*0a6a1f1dSLionel Sambuc } 72*0a6a1f1dSLionel Sambuc deleteArrayCalled(void * p)73*0a6a1f1dSLionel Sambuc void deleteArrayCalled(void * p) 74*0a6a1f1dSLionel Sambuc { 75*0a6a1f1dSLionel Sambuc assert(p); 76*0a6a1f1dSLionel Sambuc --outstanding_array_new; 77*0a6a1f1dSLionel Sambuc ++delete_array_called; 78*0a6a1f1dSLionel Sambuc } 79*0a6a1f1dSLionel Sambuc disableAllocations()80*0a6a1f1dSLionel Sambuc void disableAllocations() 81*0a6a1f1dSLionel Sambuc { 82*0a6a1f1dSLionel Sambuc disable_allocations = true; 83*0a6a1f1dSLionel Sambuc } 84*0a6a1f1dSLionel Sambuc enableAllocations()85*0a6a1f1dSLionel Sambuc void enableAllocations() 86*0a6a1f1dSLionel Sambuc { 87*0a6a1f1dSLionel Sambuc disable_allocations = false; 88*0a6a1f1dSLionel Sambuc } 89*0a6a1f1dSLionel Sambuc reset()90*0a6a1f1dSLionel Sambuc void reset() 91*0a6a1f1dSLionel Sambuc { 92*0a6a1f1dSLionel Sambuc disable_allocations = false; 93*0a6a1f1dSLionel Sambuc 94*0a6a1f1dSLionel Sambuc outstanding_new = 0; 95*0a6a1f1dSLionel Sambuc new_called = 0; 96*0a6a1f1dSLionel Sambuc delete_called = 0; 97*0a6a1f1dSLionel Sambuc last_new_size = 0; 98*0a6a1f1dSLionel Sambuc 99*0a6a1f1dSLionel Sambuc outstanding_array_new = 0; 100*0a6a1f1dSLionel Sambuc new_array_called = 0; 101*0a6a1f1dSLionel Sambuc delete_array_called = 0; 102*0a6a1f1dSLionel Sambuc last_new_array_size = 0; 103*0a6a1f1dSLionel Sambuc } 104*0a6a1f1dSLionel Sambuc 105*0a6a1f1dSLionel Sambuc public: checkOutstandingNewEq(int n) const106*0a6a1f1dSLionel Sambuc bool checkOutstandingNewEq(int n) const 107*0a6a1f1dSLionel Sambuc { 108*0a6a1f1dSLionel Sambuc return disable_checking || n == outstanding_new; 109*0a6a1f1dSLionel Sambuc } 110*0a6a1f1dSLionel Sambuc checkOutstandingNewNotEq(int n) const111*0a6a1f1dSLionel Sambuc bool checkOutstandingNewNotEq(int n) const 112*0a6a1f1dSLionel Sambuc { 113*0a6a1f1dSLionel Sambuc return disable_checking || n != outstanding_new; 114*0a6a1f1dSLionel Sambuc } 115*0a6a1f1dSLionel Sambuc checkNewCalledEq(int n) const116*0a6a1f1dSLionel Sambuc bool checkNewCalledEq(int n) const 117*0a6a1f1dSLionel Sambuc { 118*0a6a1f1dSLionel Sambuc return disable_checking || n == new_called; 119*0a6a1f1dSLionel Sambuc } 120*0a6a1f1dSLionel Sambuc checkNewCalledNotEq(int n) const121*0a6a1f1dSLionel Sambuc bool checkNewCalledNotEq(int n) const 122*0a6a1f1dSLionel Sambuc { 123*0a6a1f1dSLionel Sambuc return disable_checking || n != new_called; 124*0a6a1f1dSLionel Sambuc } 125*0a6a1f1dSLionel Sambuc checkDeleteCalledEq(int n) const126*0a6a1f1dSLionel Sambuc bool checkDeleteCalledEq(int n) const 127*0a6a1f1dSLionel Sambuc { 128*0a6a1f1dSLionel Sambuc return disable_checking || n == delete_called; 129*0a6a1f1dSLionel Sambuc } 130*0a6a1f1dSLionel Sambuc checkDeleteCalledNotEq(int n) const131*0a6a1f1dSLionel Sambuc bool checkDeleteCalledNotEq(int n) const 132*0a6a1f1dSLionel Sambuc { 133*0a6a1f1dSLionel Sambuc return disable_checking || n != delete_called; 134*0a6a1f1dSLionel Sambuc } 135*0a6a1f1dSLionel Sambuc checkLastNewSizeEq(int n) const136*0a6a1f1dSLionel Sambuc bool checkLastNewSizeEq(int n) const 137*0a6a1f1dSLionel Sambuc { 138*0a6a1f1dSLionel Sambuc return disable_checking || n == last_new_size; 139*0a6a1f1dSLionel Sambuc } 140*0a6a1f1dSLionel Sambuc checkLastNewSizeNotEq(int n) const141*0a6a1f1dSLionel Sambuc bool checkLastNewSizeNotEq(int n) const 142*0a6a1f1dSLionel Sambuc { 143*0a6a1f1dSLionel Sambuc return disable_checking || n != last_new_size; 144*0a6a1f1dSLionel Sambuc } 145*0a6a1f1dSLionel Sambuc checkOutstandingArrayNewEq(int n) const146*0a6a1f1dSLionel Sambuc bool checkOutstandingArrayNewEq(int n) const 147*0a6a1f1dSLionel Sambuc { 148*0a6a1f1dSLionel Sambuc return disable_checking || n == outstanding_array_new; 149*0a6a1f1dSLionel Sambuc } 150*0a6a1f1dSLionel Sambuc checkOutstandingArrayNewNotEq(int n) const151*0a6a1f1dSLionel Sambuc bool checkOutstandingArrayNewNotEq(int n) const 152*0a6a1f1dSLionel Sambuc { 153*0a6a1f1dSLionel Sambuc return disable_checking || n != outstanding_array_new; 154*0a6a1f1dSLionel Sambuc } 155*0a6a1f1dSLionel Sambuc checkNewArrayCalledEq(int n) const156*0a6a1f1dSLionel Sambuc bool checkNewArrayCalledEq(int n) const 157*0a6a1f1dSLionel Sambuc { 158*0a6a1f1dSLionel Sambuc return disable_checking || n == new_array_called; 159*0a6a1f1dSLionel Sambuc } 160*0a6a1f1dSLionel Sambuc checkNewArrayCalledNotEq(int n) const161*0a6a1f1dSLionel Sambuc bool checkNewArrayCalledNotEq(int n) const 162*0a6a1f1dSLionel Sambuc { 163*0a6a1f1dSLionel Sambuc return disable_checking || n != new_array_called; 164*0a6a1f1dSLionel Sambuc } 165*0a6a1f1dSLionel Sambuc checkDeleteArrayCalledEq(int n) const166*0a6a1f1dSLionel Sambuc bool checkDeleteArrayCalledEq(int n) const 167*0a6a1f1dSLionel Sambuc { 168*0a6a1f1dSLionel Sambuc return disable_checking || n == delete_array_called; 169*0a6a1f1dSLionel Sambuc } 170*0a6a1f1dSLionel Sambuc checkDeleteArrayCalledNotEq(int n) const171*0a6a1f1dSLionel Sambuc bool checkDeleteArrayCalledNotEq(int n) const 172*0a6a1f1dSLionel Sambuc { 173*0a6a1f1dSLionel Sambuc return disable_checking || n != delete_array_called; 174*0a6a1f1dSLionel Sambuc } 175*0a6a1f1dSLionel Sambuc checkLastNewArraySizeEq(int n) const176*0a6a1f1dSLionel Sambuc bool checkLastNewArraySizeEq(int n) const 177*0a6a1f1dSLionel Sambuc { 178*0a6a1f1dSLionel Sambuc return disable_checking || n == last_new_array_size; 179*0a6a1f1dSLionel Sambuc } 180*0a6a1f1dSLionel Sambuc checkLastNewArraySizeNotEq(int n) const181*0a6a1f1dSLionel Sambuc bool checkLastNewArraySizeNotEq(int n) const 182*0a6a1f1dSLionel Sambuc { 183*0a6a1f1dSLionel Sambuc return disable_checking || n != last_new_array_size; 184*0a6a1f1dSLionel Sambuc } 185*0a6a1f1dSLionel Sambuc }; 186*0a6a1f1dSLionel Sambuc 187*0a6a1f1dSLionel Sambuc #ifdef DISABLE_NEW_COUNT 188*0a6a1f1dSLionel Sambuc const bool MemCounter::disable_checking = true; 189*0a6a1f1dSLionel Sambuc #else 190*0a6a1f1dSLionel Sambuc const bool MemCounter::disable_checking = false; 191*0a6a1f1dSLionel Sambuc #endif 192*0a6a1f1dSLionel Sambuc 193*0a6a1f1dSLionel Sambuc MemCounter globalMemCounter((MemCounter::MemCounterCtorArg_())); 194*0a6a1f1dSLionel Sambuc 195*0a6a1f1dSLionel Sambuc #ifndef DISABLE_NEW_COUNT operator new(std::size_t s)196*0a6a1f1dSLionel Sambucvoid* operator new(std::size_t s) throw(std::bad_alloc) 197*0a6a1f1dSLionel Sambuc { 198*0a6a1f1dSLionel Sambuc globalMemCounter.newCalled(s); 199*0a6a1f1dSLionel Sambuc return std::malloc(s); 200*0a6a1f1dSLionel Sambuc } 201*0a6a1f1dSLionel Sambuc operator delete(void * p)202*0a6a1f1dSLionel Sambucvoid operator delete(void* p) throw() 203*0a6a1f1dSLionel Sambuc { 204*0a6a1f1dSLionel Sambuc globalMemCounter.deleteCalled(p); 205*0a6a1f1dSLionel Sambuc std::free(p); 206*0a6a1f1dSLionel Sambuc } 207*0a6a1f1dSLionel Sambuc 208*0a6a1f1dSLionel Sambuc operator new[](std::size_t s)209*0a6a1f1dSLionel Sambucvoid* operator new[](std::size_t s) throw(std::bad_alloc) 210*0a6a1f1dSLionel Sambuc { 211*0a6a1f1dSLionel Sambuc globalMemCounter.newArrayCalled(s); 212*0a6a1f1dSLionel Sambuc return operator new(s); 213*0a6a1f1dSLionel Sambuc } 214*0a6a1f1dSLionel Sambuc 215*0a6a1f1dSLionel Sambuc operator delete[](void * p)216*0a6a1f1dSLionel Sambucvoid operator delete[](void* p) throw() 217*0a6a1f1dSLionel Sambuc { 218*0a6a1f1dSLionel Sambuc globalMemCounter.deleteArrayCalled(p); 219*0a6a1f1dSLionel Sambuc operator delete(p); 220*0a6a1f1dSLionel Sambuc } 221*0a6a1f1dSLionel Sambuc 222*0a6a1f1dSLionel Sambuc #endif // DISABLE_NEW_COUNT 223*0a6a1f1dSLionel Sambuc 224*0a6a1f1dSLionel Sambuc 225*0a6a1f1dSLionel Sambuc struct DisableAllocationGuard { DisableAllocationGuardDisableAllocationGuard226*0a6a1f1dSLionel Sambuc explicit DisableAllocationGuard(bool disable = true) : m_disabled(disable) 227*0a6a1f1dSLionel Sambuc { 228*0a6a1f1dSLionel Sambuc // Don't re-disable if already disabled. 229*0a6a1f1dSLionel Sambuc if (globalMemCounter.disable_allocations == true) m_disabled = false; 230*0a6a1f1dSLionel Sambuc if (m_disabled) globalMemCounter.disableAllocations(); 231*0a6a1f1dSLionel Sambuc } 232*0a6a1f1dSLionel Sambuc releaseDisableAllocationGuard233*0a6a1f1dSLionel Sambuc void release() { 234*0a6a1f1dSLionel Sambuc if (m_disabled) globalMemCounter.enableAllocations(); 235*0a6a1f1dSLionel Sambuc m_disabled = false; 236*0a6a1f1dSLionel Sambuc } 237*0a6a1f1dSLionel Sambuc ~DisableAllocationGuardDisableAllocationGuard238*0a6a1f1dSLionel Sambuc ~DisableAllocationGuard() { 239*0a6a1f1dSLionel Sambuc release(); 240*0a6a1f1dSLionel Sambuc } 241*0a6a1f1dSLionel Sambuc 242*0a6a1f1dSLionel Sambuc private: 243*0a6a1f1dSLionel Sambuc bool m_disabled; 244*0a6a1f1dSLionel Sambuc 245*0a6a1f1dSLionel Sambuc DisableAllocationGuard(DisableAllocationGuard const&); 246*0a6a1f1dSLionel Sambuc DisableAllocationGuard& operator=(DisableAllocationGuard const&); 247*0a6a1f1dSLionel Sambuc }; 248*0a6a1f1dSLionel Sambuc 249*0a6a1f1dSLionel Sambuc #endif /* COUNT_NEW_HPP */ 250