Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
7638 views
1
/* Copyright (C) 2001-2013 Artifex Software, Inc.
2
All Rights Reserved.
3
4
This software is provided AS-IS with no warranty, either express or
5
implied.
6
7
This software is distributed under license and may not be copied, modified
8
or distributed except as expressly authorized under the terms of that
9
license. Refer to licensing information at http://www.artifex.com
10
or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
12
*/
13
14
/* Memento: A library to aid debugging of memory leaks/heap corruption.
15
*
16
* Usage:
17
* First, build your project with MEMENTO defined, and include this
18
* header file wherever you use malloc, realloc or free.
19
* This header file will use macros to point malloc, realloc and free to
20
* point to Memento_malloc, Memento_realloc, Memento_free.
21
*
22
* Run your program, and all mallocs/frees/reallocs should be redirected
23
* through here. When the program exits, you will get a list of all the
24
* leaked blocks, together with some helpful statistics. You can get the
25
* same list of allocated blocks at any point during program execution by
26
* calling Memento_listBlocks();
27
*
28
* Every call to malloc/free/realloc counts as an 'allocation event'.
29
* On each event Memento increments a counter. Every block is tagged with
30
* the current counter on allocation. Every so often during program
31
* execution, the heap is checked for consistency. By default this happens
32
* every 1024 events. This can be changed at runtime by using
33
* Memento_setParanoia(int level). 0 turns off such checking, 1 sets
34
* checking to happen on every event, any other number n sets checking to
35
* happen once every n events.
36
*
37
* Memento keeps blocks around for a while after they have been freed, and
38
* checks them as part of these heap checks to see if they have been
39
* written to (or are freed twice etc).
40
*
41
* A given heap block can be checked for consistency (it's 'pre' and
42
* 'post' guard blocks are checked to see if they have been written to)
43
* by calling Memento_checkBlock(void *blockAddress);
44
*
45
* A check of all the memory can be triggered by calling Memento_check();
46
* (or Memento_checkAllMemory(); if you'd like it to be quieter).
47
*
48
* A good place to breakpoint is Memento_breakpoint, as this will then
49
* trigger your debugger if an error is detected. This is done
50
* automatically for debug windows builds.
51
*
52
* If a block is found to be corrupt, information will be printed to the
53
* console, including the address of the block, the size of the block,
54
* the type of corruption, the number of the block and the event on which
55
* it last passed a check for correctness.
56
*
57
* If you rerun, and call Memento_paranoidAt(int event); with this number
58
* the the code will wait until it reaches that event and then start
59
* checking the heap after every allocation event. Assuming it is a
60
* deterministic failure, you should then find out where in your program
61
* the error is occurring (between event x-1 and event x).
62
*
63
* Then you can rerun the program again, and call
64
* Memento_breakAt(int event); and the program will call
65
* Memento_Breakpoint() when event x is reached, enabling you to step
66
* through.
67
*
68
* Memento_find(address) will tell you what block (if any) the given
69
* address is in.
70
*
71
* An example:
72
* Suppose we have a gs invocation that crashes with memory corruption.
73
* * Build with -DMEMENTO.
74
* * In your debugger put breakpoints on Memento_inited and
75
* Memento_Breakpoint.
76
* * Run the program. It will stop in Memento_inited.
77
* * Execute Memento_setParanoia(1); (In VS use Ctrl-Alt-Q). (Note #1)
78
* * Continue execution.
79
* * It will detect the memory corruption on the next allocation event
80
* after it happens, and stop in Memento_breakpoint. The console should
81
* show something like:
82
*
83
* Freed blocks:
84
* 0x172e610(size=288,num=1415) index 256 (0x172e710) onwards corrupted
85
* Block last checked OK at allocation 1457. Now 1458.
86
*
87
* * This means that the block became corrupted between allocation 1457
88
* and 1458 - so if we rerun and stop the program at 1457, we can then
89
* step through, possibly with a data breakpoint at 0x172e710 and see
90
* when it occurs.
91
* * So restart the program from the beginning. When we hit Memento_inited
92
* execute Memento_breakAt(1457); (and maybe Memento_setParanoia(1), or
93
* Memento_setParanoidAt(1457))
94
* * Continue execution until we hit Memento_breakpoint.
95
* * Now you can step through and watch the memory corruption happen.
96
*
97
* Note #1: Using Memento_setParanoia(1) can cause your program to run
98
* very slowly. You may instead choose to use Memento_setParanoia(100)
99
* (or some other figure). This will only exhaustively check memory on
100
* every 100th allocation event. This trades speed for the size of the
101
* average allocation event range in which detection of memory corruption
102
* occurs. You may (for example) choose to run once checking every 100
103
* allocations and discover that the corruption happens between events
104
* X and X+100. You can then rerun using Memento_paranoidAt(X), and
105
* it'll only start exhaustively checking when it reaches X.
106
*
107
* More than one memory allocator?
108
*
109
* If you have more than one memory allocator in the system (like for
110
* instance the ghostscript chunk allocator, that builds on top of the
111
* standard malloc and returns chunks itself), then there are some things
112
* to note:
113
*
114
* * If the secondary allocator gets its underlying blocks from calling
115
* malloc, then those will be checked by Memento, but 'subblocks' that
116
* are returned to the secondary allocator will not. There is currently
117
* no way to fix this other than trying to bypass the secondary
118
* allocator. One way I have found to do this with the chunk allocator
119
* is to tweak its idea of a 'large block' so that it puts every
120
* allocation in its own chunk. Clearly this negates the point of having
121
* a secondary allocator, and is therefore not recommended for general
122
* use.
123
*
124
* * Again, if the secondary allocator gets its underlying blocks from
125
* calling malloc (and hence Memento) leak detection should still work
126
* (but whole blocks will be detected rather than subblocks).
127
*
128
* * If on every allocation attempt the secondary allocator calls into
129
* Memento_failThisEvent(), and fails the allocation if it returns true
130
* then more useful features can be used; firstly memory squeezing will
131
* work, and secondly, Memento will have a "finer grained" paranoia
132
* available to it.
133
*/
134
135
#ifndef MEMENTO_H
136
137
#include <memory.h>
138
139
#ifdef __ANDROID__
140
#define MEMENTO_ANDROID
141
#include <stdio.h>
142
#include <stdlib.h>
143
#endif
144
145
#define MEMENTO_H
146
147
#ifndef MEMENTO_UNDERLYING_MALLOC
148
#define MEMENTO_UNDERLYING_MALLOC malloc
149
#endif
150
#ifndef MEMENTO_UNDERLYING_FREE
151
#define MEMENTO_UNDERLYING_FREE free
152
#endif
153
#ifndef MEMENTO_UNDERLYING_REALLOC
154
#define MEMENTO_UNDERLYING_REALLOC realloc
155
#endif
156
#ifndef MEMENTO_UNDERLYING_CALLOC
157
#define MEMENTO_UNDERLYING_CALLOC calloc
158
#endif
159
160
#ifndef MEMENTO_MAXALIGN
161
#define MEMENTO_MAXALIGN (sizeof(int))
162
#endif
163
164
#define MEMENTO_PREFILL 0xa6
165
#define MEMENTO_POSTFILL 0xa7
166
#define MEMENTO_ALLOCFILL 0xa8
167
#define MEMENTO_FREEFILL 0xa9
168
169
#define MEMENTO_FREELIST_MAX 0x2000000
170
171
int Memento_checkBlock(void *);
172
int Memento_checkAllMemory(void);
173
int Memento_check(void);
174
175
int Memento_setParanoia(int);
176
int Memento_paranoidAt(int);
177
int Memento_breakAt(int);
178
void Memento_breakOnFree(void *a);
179
void Memento_breakOnRealloc(void *a);
180
int Memento_getBlockNum(void *);
181
int Memento_find(void *a);
182
void Memento_breakpoint(void);
183
int Memento_failAt(int);
184
int Memento_failThisEvent(void);
185
void Memento_listBlocks(void);
186
void Memento_listNewBlocks(void);
187
size_t Memento_setMax(size_t);
188
void Memento_stats(void);
189
void *Memento_label(void *, const char *);
190
191
void *Memento_malloc(size_t s);
192
void *Memento_realloc(void *, size_t s);
193
void Memento_free(void *);
194
void *Memento_calloc(size_t, size_t);
195
196
#ifdef MEMENTO
197
198
#ifndef COMPILING_MEMENTO_C
199
#define malloc Memento_malloc
200
#define free Memento_free
201
#define realloc Memento_realloc
202
#define calloc Memento_calloc
203
#endif
204
205
#else
206
207
#define Memento_malloc MEMENTO_UNDERLYING_MALLOC
208
#define Memento_free MEMENTO_UNDERLYING_FREE
209
#define Memento_realloc MEMENTO_UNDERLYING_REALLOC
210
#define Memento_calloc MEMENTO_UNDERLYING_CALLOC
211
212
#define Memento_checkBlock(A) 0
213
#define Memento_checkAllMemory() 0
214
#define Memento_check() 0
215
#define Memento_setParanoia(A) 0
216
#define Memento_paranoidAt(A) 0
217
#define Memento_breakAt(A) 0
218
#define Memento_breakOnFree(A) 0
219
#define Memento_breakOnRealloc(A) 0
220
#define Memento_getBlockNum(A) 0
221
#define Memento_find(A) 0
222
#define Memento_breakpoint() do {} while (0)
223
#define Memento_failAt(A) 0
224
#define Memento_failThisEvent() 0
225
#define Memento_listBlocks() do {} while (0)
226
#define Memento_listNewBlocks() do {} while (0)
227
#define Memento_setMax(A) 0
228
#define Memento_stats() do {} while (0)
229
#define Memento_label(A,B) (A)
230
231
#endif /* MEMENTO */
232
233
#endif /* MEMENTO_H */
234
235