count_new.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. //===----------------------------------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #ifndef COUNT_NEW_H
  9. #define COUNT_NEW_H
  10. # include <cstdlib>
  11. # include <cassert>
  12. # include <new>
  13. #include "test_macros.h"
  14. #if defined(TEST_HAS_SANITIZERS)
  15. #define DISABLE_NEW_COUNT
  16. #endif
  17. namespace detail
  18. {
  19. TEST_NORETURN
  20. inline void throw_bad_alloc_helper() {
  21. #ifndef TEST_HAS_NO_EXCEPTIONS
  22. throw std::bad_alloc();
  23. #else
  24. std::abort();
  25. #endif
  26. }
  27. }
  28. class MemCounter
  29. {
  30. public:
  31. // Make MemCounter super hard to accidentally construct or copy.
  32. class MemCounterCtorArg_ {};
  33. explicit MemCounter(MemCounterCtorArg_) { reset(); }
  34. private:
  35. MemCounter(MemCounter const &);
  36. MemCounter & operator=(MemCounter const &);
  37. public:
  38. // All checks return true when disable_checking is enabled.
  39. static const bool disable_checking;
  40. // Disallow any allocations from occurring. Useful for testing that
  41. // code doesn't perform any allocations.
  42. bool disable_allocations;
  43. // number of allocations to throw after. Default (unsigned)-1. If
  44. // throw_after has the default value it will never be decremented.
  45. static const unsigned never_throw_value = static_cast<unsigned>(-1);
  46. unsigned throw_after;
  47. int outstanding_new;
  48. int new_called;
  49. int delete_called;
  50. int aligned_new_called;
  51. int aligned_delete_called;
  52. std::size_t last_new_size;
  53. std::size_t last_new_align;
  54. std::size_t last_delete_align;
  55. int outstanding_array_new;
  56. int new_array_called;
  57. int delete_array_called;
  58. int aligned_new_array_called;
  59. int aligned_delete_array_called;
  60. std::size_t last_new_array_size;
  61. std::size_t last_new_array_align;
  62. std::size_t last_delete_array_align;
  63. public:
  64. void newCalled(std::size_t s)
  65. {
  66. assert(disable_allocations == false);
  67. assert(s);
  68. if (throw_after == 0) {
  69. throw_after = never_throw_value;
  70. detail::throw_bad_alloc_helper();
  71. } else if (throw_after != never_throw_value) {
  72. --throw_after;
  73. }
  74. ++new_called;
  75. ++outstanding_new;
  76. last_new_size = s;
  77. }
  78. void alignedNewCalled(std::size_t s, std::size_t a) {
  79. newCalled(s);
  80. ++aligned_new_called;
  81. last_new_align = a;
  82. }
  83. void deleteCalled(void * p)
  84. {
  85. assert(p);
  86. --outstanding_new;
  87. ++delete_called;
  88. }
  89. void alignedDeleteCalled(void *p, std::size_t a) {
  90. deleteCalled(p);
  91. ++aligned_delete_called;
  92. last_delete_align = a;
  93. }
  94. void newArrayCalled(std::size_t s)
  95. {
  96. assert(disable_allocations == false);
  97. assert(s);
  98. if (throw_after == 0) {
  99. throw_after = never_throw_value;
  100. detail::throw_bad_alloc_helper();
  101. } else {
  102. // don't decrement throw_after here. newCalled will end up doing that.
  103. }
  104. ++outstanding_array_new;
  105. ++new_array_called;
  106. last_new_array_size = s;
  107. }
  108. void alignedNewArrayCalled(std::size_t s, std::size_t a) {
  109. newArrayCalled(s);
  110. ++aligned_new_array_called;
  111. last_new_array_align = a;
  112. }
  113. void deleteArrayCalled(void * p)
  114. {
  115. assert(p);
  116. --outstanding_array_new;
  117. ++delete_array_called;
  118. }
  119. void alignedDeleteArrayCalled(void * p, std::size_t a) {
  120. deleteArrayCalled(p);
  121. ++aligned_delete_array_called;
  122. last_delete_array_align = a;
  123. }
  124. void disableAllocations()
  125. {
  126. disable_allocations = true;
  127. }
  128. void enableAllocations()
  129. {
  130. disable_allocations = false;
  131. }
  132. void reset()
  133. {
  134. disable_allocations = false;
  135. throw_after = never_throw_value;
  136. outstanding_new = 0;
  137. new_called = 0;
  138. delete_called = 0;
  139. aligned_new_called = 0;
  140. aligned_delete_called = 0;
  141. last_new_size = 0;
  142. last_new_align = 0;
  143. outstanding_array_new = 0;
  144. new_array_called = 0;
  145. delete_array_called = 0;
  146. aligned_new_array_called = 0;
  147. aligned_delete_array_called = 0;
  148. last_new_array_size = 0;
  149. last_new_array_align = 0;
  150. }
  151. public:
  152. bool checkOutstandingNewEq(int n) const
  153. {
  154. return disable_checking || n == outstanding_new;
  155. }
  156. bool checkOutstandingNewNotEq(int n) const
  157. {
  158. return disable_checking || n != outstanding_new;
  159. }
  160. bool checkNewCalledEq(int n) const
  161. {
  162. return disable_checking || n == new_called;
  163. }
  164. bool checkNewCalledNotEq(int n) const
  165. {
  166. return disable_checking || n != new_called;
  167. }
  168. bool checkNewCalledGreaterThan(int n) const
  169. {
  170. return disable_checking || new_called > n;
  171. }
  172. bool checkDeleteCalledEq(int n) const
  173. {
  174. return disable_checking || n == delete_called;
  175. }
  176. bool checkDeleteCalledNotEq(int n) const
  177. {
  178. return disable_checking || n != delete_called;
  179. }
  180. bool checkAlignedNewCalledEq(int n) const
  181. {
  182. return disable_checking || n == aligned_new_called;
  183. }
  184. bool checkAlignedNewCalledNotEq(int n) const
  185. {
  186. return disable_checking || n != aligned_new_called;
  187. }
  188. bool checkAlignedNewCalledGreaterThan(int n) const
  189. {
  190. return disable_checking || aligned_new_called > n;
  191. }
  192. bool checkAlignedDeleteCalledEq(int n) const
  193. {
  194. return disable_checking || n == aligned_delete_called;
  195. }
  196. bool checkAlignedDeleteCalledNotEq(int n) const
  197. {
  198. return disable_checking || n != aligned_delete_called;
  199. }
  200. bool checkLastNewSizeEq(std::size_t n) const
  201. {
  202. return disable_checking || n == last_new_size;
  203. }
  204. bool checkLastNewSizeNotEq(std::size_t n) const
  205. {
  206. return disable_checking || n != last_new_size;
  207. }
  208. bool checkLastNewAlignEq(std::size_t n) const
  209. {
  210. return disable_checking || n == last_new_align;
  211. }
  212. bool checkLastNewAlignNotEq(std::size_t n) const
  213. {
  214. return disable_checking || n != last_new_align;
  215. }
  216. bool checkLastDeleteAlignEq(std::size_t n) const
  217. {
  218. return disable_checking || n == last_delete_align;
  219. }
  220. bool checkLastDeleteAlignNotEq(std::size_t n) const
  221. {
  222. return disable_checking || n != last_delete_align;
  223. }
  224. bool checkOutstandingArrayNewEq(int n) const
  225. {
  226. return disable_checking || n == outstanding_array_new;
  227. }
  228. bool checkOutstandingArrayNewNotEq(int n) const
  229. {
  230. return disable_checking || n != outstanding_array_new;
  231. }
  232. bool checkNewArrayCalledEq(int n) const
  233. {
  234. return disable_checking || n == new_array_called;
  235. }
  236. bool checkNewArrayCalledNotEq(int n) const
  237. {
  238. return disable_checking || n != new_array_called;
  239. }
  240. bool checkDeleteArrayCalledEq(int n) const
  241. {
  242. return disable_checking || n == delete_array_called;
  243. }
  244. bool checkDeleteArrayCalledNotEq(int n) const
  245. {
  246. return disable_checking || n != delete_array_called;
  247. }
  248. bool checkAlignedNewArrayCalledEq(int n) const
  249. {
  250. return disable_checking || n == aligned_new_array_called;
  251. }
  252. bool checkAlignedNewArrayCalledNotEq(int n) const
  253. {
  254. return disable_checking || n != aligned_new_array_called;
  255. }
  256. bool checkAlignedNewArrayCalledGreaterThan(int n) const
  257. {
  258. return disable_checking || aligned_new_array_called > n;
  259. }
  260. bool checkAlignedDeleteArrayCalledEq(int n) const
  261. {
  262. return disable_checking || n == aligned_delete_array_called;
  263. }
  264. bool checkAlignedDeleteArrayCalledNotEq(int n) const
  265. {
  266. return disable_checking || n != aligned_delete_array_called;
  267. }
  268. bool checkLastNewArraySizeEq(std::size_t n) const
  269. {
  270. return disable_checking || n == last_new_array_size;
  271. }
  272. bool checkLastNewArraySizeNotEq(std::size_t n) const
  273. {
  274. return disable_checking || n != last_new_array_size;
  275. }
  276. bool checkLastNewArrayAlignEq(std::size_t n) const
  277. {
  278. return disable_checking || n == last_new_array_align;
  279. }
  280. bool checkLastNewArrayAlignNotEq(std::size_t n) const
  281. {
  282. return disable_checking || n != last_new_array_align;
  283. }
  284. };
  285. #ifdef DISABLE_NEW_COUNT
  286. const bool MemCounter::disable_checking = true;
  287. #else
  288. const bool MemCounter::disable_checking = false;
  289. #endif
  290. inline MemCounter* getGlobalMemCounter() {
  291. static MemCounter counter((MemCounter::MemCounterCtorArg_()));
  292. return &counter;
  293. }
  294. MemCounter &globalMemCounter = *getGlobalMemCounter();
  295. #ifndef DISABLE_NEW_COUNT
  296. void* operator new(std::size_t s) TEST_THROW_SPEC(std::bad_alloc)
  297. {
  298. getGlobalMemCounter()->newCalled(s);
  299. void* ret = std::malloc(s);
  300. if (ret == nullptr)
  301. detail::throw_bad_alloc_helper();
  302. return ret;
  303. }
  304. void operator delete(void* p) TEST_NOEXCEPT
  305. {
  306. getGlobalMemCounter()->deleteCalled(p);
  307. std::free(p);
  308. }
  309. void* operator new[](std::size_t s) TEST_THROW_SPEC(std::bad_alloc)
  310. {
  311. getGlobalMemCounter()->newArrayCalled(s);
  312. return operator new(s);
  313. }
  314. void operator delete[](void* p) TEST_NOEXCEPT
  315. {
  316. getGlobalMemCounter()->deleteArrayCalled(p);
  317. operator delete(p);
  318. }
  319. #ifndef TEST_HAS_NO_ALIGNED_ALLOCATION
  320. #if defined(_LIBCPP_MSVCRT_LIKE) || \
  321. (!defined(_LIBCPP_VERSION) && defined(_WIN32))
  322. #define USE_ALIGNED_ALLOC
  323. #endif
  324. void* operator new(std::size_t s, std::align_val_t av) TEST_THROW_SPEC(std::bad_alloc) {
  325. const std::size_t a = static_cast<std::size_t>(av);
  326. getGlobalMemCounter()->alignedNewCalled(s, a);
  327. void *ret;
  328. #ifdef USE_ALIGNED_ALLOC
  329. ret = _aligned_malloc(s, a);
  330. #else
  331. posix_memalign(&ret, a, s);
  332. #endif
  333. if (ret == nullptr)
  334. detail::throw_bad_alloc_helper();
  335. return ret;
  336. }
  337. void operator delete(void *p, std::align_val_t av) TEST_NOEXCEPT {
  338. const std::size_t a = static_cast<std::size_t>(av);
  339. getGlobalMemCounter()->alignedDeleteCalled(p, a);
  340. if (p) {
  341. #ifdef USE_ALIGNED_ALLOC
  342. ::_aligned_free(p);
  343. #else
  344. ::free(p);
  345. #endif
  346. }
  347. }
  348. void* operator new[](std::size_t s, std::align_val_t av) TEST_THROW_SPEC(std::bad_alloc) {
  349. const std::size_t a = static_cast<std::size_t>(av);
  350. getGlobalMemCounter()->alignedNewArrayCalled(s, a);
  351. return operator new(s, av);
  352. }
  353. void operator delete[](void *p, std::align_val_t av) TEST_NOEXCEPT {
  354. const std::size_t a = static_cast<std::size_t>(av);
  355. getGlobalMemCounter()->alignedDeleteArrayCalled(p, a);
  356. return operator delete(p, av);
  357. }
  358. #endif // TEST_HAS_NO_ALIGNED_ALLOCATION
  359. #endif // DISABLE_NEW_COUNT
  360. struct DisableAllocationGuard {
  361. explicit DisableAllocationGuard(bool disable = true) : m_disabled(disable)
  362. {
  363. // Don't re-disable if already disabled.
  364. if (globalMemCounter.disable_allocations == true) m_disabled = false;
  365. if (m_disabled) globalMemCounter.disableAllocations();
  366. }
  367. void release() {
  368. if (m_disabled) globalMemCounter.enableAllocations();
  369. m_disabled = false;
  370. }
  371. ~DisableAllocationGuard() {
  372. release();
  373. }
  374. private:
  375. bool m_disabled;
  376. DisableAllocationGuard(DisableAllocationGuard const&);
  377. DisableAllocationGuard& operator=(DisableAllocationGuard const&);
  378. };
  379. struct RequireAllocationGuard {
  380. explicit RequireAllocationGuard(std::size_t RequireAtLeast = 1)
  381. : m_req_alloc(RequireAtLeast),
  382. m_new_count_on_init(globalMemCounter.new_called),
  383. m_outstanding_new_on_init(globalMemCounter.outstanding_new),
  384. m_exactly(false)
  385. {
  386. }
  387. void requireAtLeast(std::size_t N) { m_req_alloc = N; m_exactly = false; }
  388. void requireExactly(std::size_t N) { m_req_alloc = N; m_exactly = true; }
  389. ~RequireAllocationGuard() {
  390. assert(globalMemCounter.checkOutstandingNewEq(static_cast<int>(m_outstanding_new_on_init)));
  391. std::size_t Expect = m_new_count_on_init + m_req_alloc;
  392. assert(globalMemCounter.checkNewCalledEq(static_cast<int>(Expect)) ||
  393. (!m_exactly && globalMemCounter.checkNewCalledGreaterThan(static_cast<int>(Expect))));
  394. }
  395. private:
  396. std::size_t m_req_alloc;
  397. const std::size_t m_new_count_on_init;
  398. const std::size_t m_outstanding_new_on_init;
  399. bool m_exactly;
  400. RequireAllocationGuard(RequireAllocationGuard const&);
  401. RequireAllocationGuard& operator=(RequireAllocationGuard const&);
  402. };
  403. #endif /* COUNT_NEW_H */