blob: dac99e052803e2e1cbcfa50d3ef802b64f983878 [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) \
13 || __has_feature(memory_sanitizer)
14#define DISABLE_NEW_COUNT
15#endif
16
17class MemCounter
18{
19public:
20 // Make MemCounter super hard to accidentally construct or copy.
21 class MemCounterCtorArg_ {};
22 explicit MemCounter(MemCounterCtorArg_) {}
23
24private:
25 MemCounter(MemCounter const &);
26 MemCounter & operator=(MemCounter const &);
27
28public:
29 // All checks return true when disable_checking is enabled.
30 static const bool disable_checking;
31
32 int outstanding_new = 0;
33 int new_called = 0;
34 int delete_called = 0;
35 int last_new_size = 0;
36
37 int outstanding_array_new = 0;
38 int new_array_called = 0;
39 int delete_array_called = 0;
40 int last_new_array_size = 0;
41
42public:
43 void newCalled(std::size_t s)
44 {
45 assert(s);
46 ++new_called;
47 ++outstanding_new;
48 last_new_size = s;
49 }
50
51 void deleteCalled(void * p)
52 {
53 assert(p);
54 --outstanding_new;
55 ++delete_called;
56 }
57
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
66 void deleteArrayCalled(void * p)
67 {
68 assert(p);
69 --outstanding_array_new;
70 ++delete_array_called;
71 }
72
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
86public:
87 bool checkOutstandingNewEq(int n) const
88 {
89 return disable_checking || n == outstanding_new;
90 }
91
92 bool checkOutstandingNewNotEq(int n) const
93 {
94 return disable_checking || n != outstanding_new;
95 }
96
97 bool checkNewCalledEq(int n) const
98 {
99 return disable_checking || n == new_called;
100 }
101
102 bool checkNewCalledNotEq(int n) const
103 {
104 return disable_checking || n != new_called;
105 }
106
107 bool checkDeleteCalledEq(int n) const
108 {
109 return disable_checking || n == delete_called;
110 }
111
112 bool checkDeleteCalledNotEq(int n) const
113 {
114 return disable_checking || n != delete_called;
115 }
116
117 bool checkLastNewSizeEq(int n) const
118 {
119 return disable_checking || n == last_new_size;
120 }
121
122 bool checkLastNewSizeNotEq(int n) const
123 {
124 return disable_checking || n != last_new_size;
125 }
126
127 bool checkOutstandingArrayNewEq(int n) const
128 {
129 return disable_checking || n == outstanding_array_new;
130 }
131
132 bool checkOutstandingArrayNewNotEq(int n) const
133 {
134 return disable_checking || n != outstanding_array_new;
135 }
136
137 bool checkNewArrayCalledEq(int n) const
138 {
139 return disable_checking || n == new_array_called;
140 }
141
142 bool checkNewArrayCalledNotEq(int n) const
143 {
144 return disable_checking || n != new_array_called;
145 }
146
147 bool checkDeleteArrayCalledEq(int n) const
148 {
149 return disable_checking || n == delete_array_called;
150 }
151
152 bool checkDeleteArrayCalledNotEq(int n) const
153 {
154 return disable_checking || n != delete_array_called;
155 }
156
157 bool checkLastNewArraySizeEq(int n) const
158 {
159 return disable_checking || n == last_new_array_size;
160 }
161
162 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
174MemCounter globalMemCounter((MemCounter::MemCounterCtorArg_()));
175
176#ifndef DISABLE_NEW_COUNT
177void* operator new(std::size_t s) throw(std::bad_alloc)
178{
179 globalMemCounter.newCalled(s);
180 return std::malloc(s);
181}
182
183void operator delete(void* p) throw()
184{
185 globalMemCounter.deleteCalled(p);
186 std::free(p);
187}
188
189
190void* operator new[](std::size_t s) throw(std::bad_alloc)
191{
192 globalMemCounter.newArrayCalled(s);
193 return operator new(s);
194}
195
196
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 */