1 #ifndef COUNT_NEW_HPP 2 #define COUNT_NEW_HPP 3 4 # include <cstdlib> 5 # include <cassert> 6 # include <new> 7 8 #ifndef __has_feature 9 # define __has_feature(x) 0 10 #endif 11 12 #if __has_feature(address_sanitizer) \ 13 || __has_feature(memory_sanitizer) 14 #define DISABLE_NEW_COUNT 15 #endif 16 17 class MemCounter 18 { 19 public: 20 // Make MemCounter super hard to accidentally construct or copy. 21 class MemCounterCtorArg_ {}; MemCounter(MemCounterCtorArg_)22 explicit MemCounter(MemCounterCtorArg_) { reset(); } 23 24 private: 25 MemCounter(MemCounter const &); 26 MemCounter & operator=(MemCounter const &); 27 28 public: 29 // All checks return true when disable_checking is enabled. 30 static const bool disable_checking; 31 32 int outstanding_new; 33 int new_called; 34 int delete_called; 35 int last_new_size; 36 37 int outstanding_array_new; 38 int new_array_called; 39 int delete_array_called; 40 int last_new_array_size; 41 42 public: newCalled(std::size_t s)43 void newCalled(std::size_t s) 44 { 45 assert(s); 46 ++new_called; 47 ++outstanding_new; 48 last_new_size = s; 49 } 50 deleteCalled(void * p)51 void deleteCalled(void * p) 52 { 53 assert(p); 54 --outstanding_new; 55 ++delete_called; 56 } 57 newArrayCalled(std::size_t s)58 void newArrayCalled(std::size_t s) 59 { 60 assert(s); 61 ++outstanding_array_new; 62 ++new_array_called; 63 last_new_array_size = s; 64 } 65 deleteArrayCalled(void * p)66 void deleteArrayCalled(void * p) 67 { 68 assert(p); 69 --outstanding_array_new; 70 ++delete_array_called; 71 } 72 reset()73 void reset() 74 { 75 outstanding_new = 0; 76 new_called = 0; 77 delete_called = 0; 78 last_new_size = 0; 79 80 outstanding_array_new = 0; 81 new_array_called = 0; 82 delete_array_called = 0; 83 last_new_array_size = 0; 84 } 85 86 public: checkOutstandingNewEq(int n) const87 bool checkOutstandingNewEq(int n) const 88 { 89 return disable_checking || n == outstanding_new; 90 } 91 checkOutstandingNewNotEq(int n) const92 bool checkOutstandingNewNotEq(int n) const 93 { 94 return disable_checking || n != outstanding_new; 95 } 96 checkNewCalledEq(int n) const97 bool checkNewCalledEq(int n) const 98 { 99 return disable_checking || n == new_called; 100 } 101 checkNewCalledNotEq(int n) const102 bool checkNewCalledNotEq(int n) const 103 { 104 return disable_checking || n != new_called; 105 } 106 checkDeleteCalledEq(int n) const107 bool checkDeleteCalledEq(int n) const 108 { 109 return disable_checking || n == delete_called; 110 } 111 checkDeleteCalledNotEq(int n) const112 bool checkDeleteCalledNotEq(int n) const 113 { 114 return disable_checking || n != delete_called; 115 } 116 checkLastNewSizeEq(int n) const117 bool checkLastNewSizeEq(int n) const 118 { 119 return disable_checking || n == last_new_size; 120 } 121 checkLastNewSizeNotEq(int n) const122 bool checkLastNewSizeNotEq(int n) const 123 { 124 return disable_checking || n != last_new_size; 125 } 126 checkOutstandingArrayNewEq(int n) const127 bool checkOutstandingArrayNewEq(int n) const 128 { 129 return disable_checking || n == outstanding_array_new; 130 } 131 checkOutstandingArrayNewNotEq(int n) const132 bool checkOutstandingArrayNewNotEq(int n) const 133 { 134 return disable_checking || n != outstanding_array_new; 135 } 136 checkNewArrayCalledEq(int n) const137 bool checkNewArrayCalledEq(int n) const 138 { 139 return disable_checking || n == new_array_called; 140 } 141 checkNewArrayCalledNotEq(int n) const142 bool checkNewArrayCalledNotEq(int n) const 143 { 144 return disable_checking || n != new_array_called; 145 } 146 checkDeleteArrayCalledEq(int n) const147 bool checkDeleteArrayCalledEq(int n) const 148 { 149 return disable_checking || n == delete_array_called; 150 } 151 checkDeleteArrayCalledNotEq(int n) const152 bool checkDeleteArrayCalledNotEq(int n) const 153 { 154 return disable_checking || n != delete_array_called; 155 } 156 checkLastNewArraySizeEq(int n) const157 bool checkLastNewArraySizeEq(int n) const 158 { 159 return disable_checking || n == last_new_array_size; 160 } 161 checkLastNewArraySizeNotEq(int n) const162 bool checkLastNewArraySizeNotEq(int n) const 163 { 164 return disable_checking || n != last_new_array_size; 165 } 166 }; 167 168 #ifdef DISABLE_NEW_COUNT 169 const bool MemCounter::disable_checking = true; 170 #else 171 const bool MemCounter::disable_checking = false; 172 #endif 173 174 MemCounter globalMemCounter((MemCounter::MemCounterCtorArg_())); 175 176 #ifndef DISABLE_NEW_COUNT operator new(std::size_t s)177void* operator new(std::size_t s) throw(std::bad_alloc) 178 { 179 globalMemCounter.newCalled(s); 180 return std::malloc(s); 181 } 182 operator delete(void * p)183void operator delete(void* p) throw() 184 { 185 globalMemCounter.deleteCalled(p); 186 std::free(p); 187 } 188 189 operator new[](std::size_t s)190void* operator new[](std::size_t s) throw(std::bad_alloc) 191 { 192 globalMemCounter.newArrayCalled(s); 193 return operator new(s); 194 } 195 196 operator delete[](void * p)197void operator delete[](void* p) throw() 198 { 199 globalMemCounter.deleteArrayCalled(p); 200 operator delete(p); 201 } 202 203 #endif // DISABLE_NEW_COUNT 204 205 #endif /* COUNT_NEW_HPP */ 206