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