1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 *
16 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17 * All rights reserved.
18 */
19
20 /** \file
21 * \ingroup MEM
22 *
23 * \brief Read \ref MEMPage
24 *
25 * \page MEMPage Guarded memory(de)allocation
26 *
27 * \section aboutmem c-style guarded memory allocation
28 *
29 * \subsection memabout About the MEM module
30 *
31 * MEM provides guarded malloc/calloc calls. All memory is enclosed by
32 * pads, to detect out-of-bound writes. All blocks are placed in a
33 * linked list, so they remain reachable at all times. There is no
34 * back-up in case the linked-list related data is lost.
35 *
36 * \subsection memissues Known issues with MEM
37 *
38 * There are currently no known issues with MEM. Note that there is a
39 * second intern/ module with MEM_ prefix, for use in c++.
40 *
41 * \subsection memdependencies Dependencies
42 * - stdlib
43 * - stdio
44 *
45 * \subsection memdocs API Documentation
46 * See \ref MEM_guardedalloc.h
47 */
48
49 #ifndef __MEM_GUARDEDALLOC_H__
50 #define __MEM_GUARDEDALLOC_H__
51
52 #include <stdio.h> /* needed for FILE* */
53
54 /* needed for uintptr_t and attributes, exception, dont use BLI anywhere else in MEM_* */
55 #include "../../source/blender/blenlib/BLI_compiler_attrs.h"
56 #include "../../source/blender/blenlib/BLI_sys_types.h"
57
58 #ifdef __cplusplus
59 extern "C" {
60 #endif
61
62 /** Returns the length of the allocated memory segment pointed at
63 * by vmemh. If the pointer was not previously allocated by this
64 * module, the result is undefined.*/
65 extern size_t (*MEM_allocN_len)(const void *vmemh) ATTR_WARN_UNUSED_RESULT;
66
67 /**
68 * Release memory previously allocated by this module.
69 */
70 extern void (*MEM_freeN)(void *vmemh);
71
72 #if 0 /* UNUSED */
73 /**
74 * Return zero if memory is not in allocated list
75 */
76 extern short (*MEM_testN)(void *vmemh);
77 #endif
78
79 /**
80 * Duplicates a block of memory, and returns a pointer to the
81 * newly allocated block. */
82 extern void *(*MEM_dupallocN)(const void *vmemh) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT;
83
84 /**
85 * Reallocates a block of memory, and returns pointer to the newly
86 * allocated block, the old one is freed. this is not as optimized
87 * as a system realloc but just makes a new allocation and copies
88 * over from existing memory. */
89 extern void *(*MEM_reallocN_id)(void *vmemh,
90 size_t len,
91 const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT
92 ATTR_ALLOC_SIZE(2);
93
94 /**
95 * A variant of realloc which zeros new bytes
96 */
97 extern void *(*MEM_recallocN_id)(void *vmemh,
98 size_t len,
99 const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT
100 ATTR_ALLOC_SIZE(2);
101
102 #define MEM_reallocN(vmemh, len) MEM_reallocN_id(vmemh, len, __func__)
103 #define MEM_recallocN(vmemh, len) MEM_recallocN_id(vmemh, len, __func__)
104
105 /**
106 * Allocate a block of memory of size len, with tag name str. The
107 * memory is cleared. The name must be static, because only a
108 * pointer to it is stored ! */
109 extern void *(*MEM_callocN)(size_t len, const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT
110 ATTR_ALLOC_SIZE(1) ATTR_NONNULL(2);
111
112 /**
113 * Allocate a block of memory of size (len * size), with tag name
114 * str, aborting in case of integer overflows to prevent vulnerabilities.
115 * The memory is cleared. The name must be static, because only a
116 * pointer to it is stored ! */
117 extern void *(*MEM_calloc_arrayN)(size_t len,
118 size_t size,
119 const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT
120 ATTR_ALLOC_SIZE(1, 2) ATTR_NONNULL(3);
121
122 /**
123 * Allocate a block of memory of size len, with tag name str. The
124 * name must be a static, because only a pointer to it is stored !
125 * */
126 extern void *(*MEM_mallocN)(size_t len, const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT
127 ATTR_ALLOC_SIZE(1) ATTR_NONNULL(2);
128
129 /**
130 * Allocate a block of memory of size (len * size), with tag name str,
131 * aborting in case of integer overflow to prevent vulnerabilities. The
132 * name must be a static, because only a pointer to it is stored !
133 * */
134 extern void *(*MEM_malloc_arrayN)(size_t len,
135 size_t size,
136 const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT
137 ATTR_ALLOC_SIZE(1, 2) ATTR_NONNULL(3);
138
139 /**
140 * Allocate an aligned block of memory of size len, with tag name str. The
141 * name must be a static, because only a pointer to it is stored !
142 * */
143 extern void *(*MEM_mallocN_aligned)(size_t len,
144 size_t alignment,
145 const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT
146 ATTR_ALLOC_SIZE(1) ATTR_NONNULL(3);
147
148 /** Print a list of the names and sizes of all allocated memory
149 * blocks. as a python dict for easy investigation */
150 extern void (*MEM_printmemlist_pydict)(void);
151
152 /** Print a list of the names and sizes of all allocated memory
153 * blocks. */
154 extern void (*MEM_printmemlist)(void);
155
156 /** calls the function on all allocated memory blocks. */
157 extern void (*MEM_callbackmemlist)(void (*func)(void *));
158
159 /** Print statistics about memory usage */
160 extern void (*MEM_printmemlist_stats)(void);
161
162 /** Set the callback function for error output. */
163 extern void (*MEM_set_error_callback)(void (*func)(const char *));
164
165 /**
166 * Are the start/end block markers still correct ?
167 *
168 * \retval true for correct memory, false for corrupted memory. */
169 extern bool (*MEM_consistency_check)(void);
170
171 /** Attempt to enforce OSX (or other OS's) to have malloc and stack nonzero */
172 extern void (*MEM_set_memory_debug)(void);
173
174 /** Memory usage stats. */
175 extern size_t (*MEM_get_memory_in_use)(void);
176 /** Get amount of memory blocks in use. */
177 extern unsigned int (*MEM_get_memory_blocks_in_use)(void);
178
179 /** Reset the peak memory statistic to zero. */
180 extern void (*MEM_reset_peak_memory)(void);
181
182 /** Get the peak memory usage in bytes, including mmap allocations. */
183 extern size_t (*MEM_get_peak_memory)(void) ATTR_WARN_UNUSED_RESULT;
184
185 #ifdef __GNUC__
186 # define MEM_SAFE_FREE(v) \
187 do { \
188 typeof(&(v)) _v = &(v); \
189 if (*_v) { \
190 /* Cast so we can free constant arrays. */ \
191 MEM_freeN((void *)*_v); \
192 *_v = NULL; \
193 } \
194 } while (0)
195 #else
196 # define MEM_SAFE_FREE(v) \
197 do { \
198 void **_v = (void **)&(v); \
199 if (*_v) { \
200 MEM_freeN(*_v); \
201 *_v = NULL; \
202 } \
203 } while (0)
204 #endif
205
206 /* overhead for lockfree allocator (use to avoid slop-space) */
207 #define MEM_SIZE_OVERHEAD sizeof(size_t)
208 #define MEM_SIZE_OPTIMAL(size) ((size)-MEM_SIZE_OVERHEAD)
209
210 #ifndef NDEBUG
211 extern const char *(*MEM_name_ptr)(void *vmemh);
212 #endif
213
214 /** This should be called as early as possible in the program. When it has been called, information
215 * about memory leaks will be printed on exit. */
216 void MEM_init_memleak_detection(void);
217
218 /**
219 * Use this if we want to call #exit during argument parsing for example,
220 * without having to free all data.
221 */
222 void MEM_use_memleak_detection(bool enabled);
223
224 /** When this has been called and memory leaks have been detected, the process will have an exit
225 * code that indicates failure. This can be used for when checking for memory leaks with automated
226 * tests. */
227 void MEM_enable_fail_on_memleak(void);
228
229 /* Switch allocator to slower but fully guarded mode. */
230 void MEM_use_guarded_allocator(void);
231
232 #ifdef __cplusplus
233 }
234 #endif /* __cplusplus */
235
236 #ifdef __cplusplus
237 /* alloc funcs for C++ only */
238 # define MEM_CXX_CLASS_ALLOC_FUNCS(_id) \
239 public: \
240 void *operator new(size_t num_bytes) \
241 { \
242 return MEM_mallocN(num_bytes, _id); \
243 } \
244 void operator delete(void *mem) \
245 { \
246 if (mem) { \
247 MEM_freeN(mem); \
248 } \
249 } \
250 void *operator new[](size_t num_bytes) \
251 { \
252 return MEM_mallocN(num_bytes, _id "[]"); \
253 } \
254 void operator delete[](void *mem) \
255 { \
256 if (mem) { \
257 MEM_freeN(mem); \
258 } \
259 } \
260 void *operator new(size_t /*count*/, void *ptr) \
261 { \
262 return ptr; \
263 } \
264 /* This is the matching delete operator to the placement-new operator above. Both parameters \
265 * will have the same value. Without this, we get the warning C4291 on windows. */ \
266 void operator delete(void * /*ptr_to_free*/, void * /*ptr*/) \
267 { \
268 }
269
270 /* Needed when type includes a namespace, then the namespace should not be
271 * specified after ~, so using a macro fails. */
OBJECT_GUARDED_DESTRUCTOR(T * what)272 template<class T> inline void OBJECT_GUARDED_DESTRUCTOR(T *what)
273 {
274 what->~T();
275 }
276
277 # if defined __GNUC__
278 # define OBJECT_GUARDED_NEW(type, args...) new (MEM_mallocN(sizeof(type), __func__)) type(args)
279 # else
280 # define OBJECT_GUARDED_NEW(type, ...) \
281 new (MEM_mallocN(sizeof(type), __FUNCTION__)) type(__VA_ARGS__)
282 # endif
283 # define OBJECT_GUARDED_DELETE(what, type) \
284 { \
285 if (what) { \
286 OBJECT_GUARDED_DESTRUCTOR((type *)what); \
287 MEM_freeN(what); \
288 } \
289 } \
290 (void)0
291 # define OBJECT_GUARDED_SAFE_DELETE(what, type) \
292 { \
293 if (what) { \
294 OBJECT_GUARDED_DESTRUCTOR((type *)what); \
295 MEM_freeN(what); \
296 what = NULL; \
297 } \
298 } \
299 (void)0
300 #endif /* __cplusplus */
301
302 #endif /* __MEM_GUARDEDALLOC_H__ */
303