1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
/*
Copyright 1990-2008 Light Infocon Tecnologia S/A
Este arquivo é parte do programa LightBase - Banco de Dados Textual Documental
O LightBase é um software livre; você pode redistribui-lo e/ou modifica-lo dentro
dos termos da Licença Pública Geral GNU como publicada pela Fundação do Software
Livre (FSF); na versão 2 da Licença.
Este programa é distribuído na esperança que possa ser útil, mas SEM NENHUMA
GARANTIA; sem uma garantia implícita de ADEQUAÇÃO a qualquer MERCADO ou APLICAÇÃO
EM PARTICULAR. Veja a Licença Pública Geral GNU para maiores detalhes.
Você deve ter recebido uma cópia da Licença Pública Geral GNU versao 2, sob o
título "LICENCA.txt", junto com este programa, se não, escreva para a Fundação do
Software Livre(FSF) Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
//
// The MS-DOS heapwalk functions are in different header files depending
// on who you are. Note that I don't walk the heap under MS-DOS with
// Symantec or Watcom. Not sure if I can.
//
//
// Walking the Windows heap requires TOOLHELP.DLL. It would be great
// if Borland provided the TOOLHELP API under their DPMI extenders, but
// I don't think they do. I don't think the heap walk functions are
// available under Win 32s either.
//
//
// If I am using 16 bit Powerpack in a DLL, this stuff doesn't work. I
// detect it and disable it.
//
/*
* To completely eliminate this stuff, all you have to do is define
* AL_DISABLE_NEW before rebuilding the library.
*/
//
// When I pop up an error message, it sometimes helps to know where it came
// from. This definition is used to create the message box.
//
//
// If Debug is not turned on, none of this stuff happens. I also don't
// work with Microsoft huge model, things get nasty in there.
//
//
// int PointerInHeap( void *p )
//
// ARGUMENTS:
//
// p : The pointer under test.
//
// RETURNS
//
// An integer, true or false.
//
// DESCRIPTION
//
// This function is called by ::delete() to see if the pointer we are
// trying to delete is in fact in the heap. If it isn't, we could cause
// quite a bit of trouble if we try to delete it.
//
// Under MS-DOS, this function just executes the normal heapwalk functions
// supported by Microsoft and Borland. Under Windows small memory
// models, we use the Toohelp API to walk the local heap. Under all
// other circumstances, we just give up and always return a true value.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
//
// This is the Microsoft MS-DOS version. It seems to also work
// with Win32s, and Windows NT Console. Very confusing,
// I hope the #ifdefs all work out!
//
// This function just uses the heapwalk RTL function to check for the
// presence of the pointer in the heap.
//
int
//
// This is the Borland MS-DOS version. It looks like it also works under
// Win 32s, which might be more reasonable, since we do support Borland
// in that mode.
//
// Like the previous function, this guy just uses the heapwalk API to
// check the local heap for the presence of the pointer.
//
int
//
// Microsoft is nice enough to support the heapwalk API under Windows
// large memory models also. This is good, since the TOOLHELP API would
// flounder when confronted with a subsegment allocation strategy.
//
int
//
// Under Windows small and medium memory models, the TOOLHELP API lets
// us walk the local heap, looking for an entry. No subsegment allocation
// scheme will get in the way.
//
// I should be able to use this with Watcom, but I am using a little bit of
// inline assembly to get my data segment. This inline assembly won't
// work with Watcom, so someday I will have to add a little code to
// get things working right with them also.
//
int
//
// When all else fails, give up!
//
int
//
// void *operator new( size_t size )
//
// ARGUMENTS:
//
// size : The amount of memory being requested.
//
// RETURNS
//
// A pointer to the newly allocated storage area, or a 0 in the event
// of failure.
//
// DESCRIPTION
//
// This version of ::new() does what I described at the top of the file.
// It allocates a block of memory as requested, and includes eight
// extra bytes. Four bytes are reserved at the start and end of the memory
// block for our "pickets". These pickets hold a fixed pattern in memory
// that can be tested for accidental modification. When ::delete() is
// called, we check the area to see if the caller munged it, and
// cause an assertion error if they did. The other four bytes are needed
// to keep the size of the block on hand. Otherwise I wouldn't know how
// to get to the end of the block to check the trailing picket.
//
// Note that if you are using set_new_handler() or exceptions, this stuff
// is probably going to hose you up badly.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
// July 7, 1994 1.0B : On Sun UNIX, if I tried to write a long out to
// a misaligned address, I get a fault. The leading
// pickets will always be properly aligned, but the
// trailing picket could land anywhere. So, under
// UNIX, I store the trailing picket a byte at a time.
void *operator new
//
// void operator delete( void *ptr )
//
// ARGUMENTS:
//
// ptr : A pointer to the memory block the user wishes to delete.
//
// RETURNS
//
// Nothing.
//
// DESCRIPTION
//
// After the user has had the chance to muck with this memory block for
// a while, he or she will want to return it to the heap. We do a bunch
// of checks here before that happens, to see if any serious mistakes have
// been made. If we detect any serious mistakes, we just abort the
// program with an assertion error.
//
// First we check to see if Windows thinks it is even a valid pointer. If
// we don't do this, some of the other code here will GPF if you call delete
// with a really bad pointer. Those GPFs are a lot less informative than
// our nice assertion failures.
//
// If it looks like it is a valid pointer, the next thing we do is try to
// see if the pointer is in our heap. A common mistake is trying to free
// a pointer twice, or freeing a pointer that has been incremented or
// decremented. Either of these can royally foul the heap.
//
// If it looks like the pointer really is in the heap, there is still one
// last thing to check. I take a quick glance at both the leading and
// trailing pickets to see if either of them have been mangled. A simple
// overwrite or underwrite by just one byte can be catastrophic, but we
// detect it easily here.
//
// If all of that goes as expected, we are free to finally return the
// storage to the heap. Just for good luck, I clear it out first. That
// way if anyone is foolish enough to try and use the data after it has
// been deleted, they will at least see that there is nothing intelligent
// store there.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
// July 7, 1994 1.0B : On Sun UNIX, if I tried to read a long from
// a misaligned address, I get a fault. The leading
// pickets will always be properly aligned, but the
// trailing picket could land anywhere. So, under
// UNIX, I check the trailing picket a byte at a time.
void operator delete
//#ifdef _DEBUG etc.
// #ifdef AL_DISABLE_NEW