1N/A * Copyright (c) 2000-2001, 2004 Sendmail, Inc. and its suppliers. 1N/A * All rights reserved. 1N/A * By using this file, you agree to the terms and conditions set 1N/A * forth in the LICENSE file which can be found at the top level of 1N/A * the sendmail distribution. 1N/A#
pragma ident "%Z%%M% %I% %E% SMI" 1N/A** debugging memory allocation package 1N/A/* undef all macro versions of the "functions" so they can be specified here */ 1N/A#
endif /* SM_HEAP_CHECK */ 1N/A "@(#)$Debug: sm_check_heap - check sm_malloc, sm_realloc, sm_free calls $");
1N/A#
endif /* SM_HEAP_CHECK */ 1N/A** The behaviour of malloc with size==0 is platform dependent (it 1N/A** says so in the C standard): it can return NULL or non-NULL. We 1N/A** don't want sm_malloc_x(0) to raise an exception on some platforms 1N/A** but not others, so this case requires special handling. We've got 1N/A** two choices: "size = 1" or "return NULL". We use the former in the 1N/A** If we had something like autoconf we could figure out the 1N/A** behaviour of the platform and either use this hack or just 1N/A** SM_MALLOC_X -- wrapper around malloc(), raises an exception on error. 1N/A** size -- size of requested memory. 1N/A** Pointer to memory region. 1N/A** sm_malloc_x only gets called from source files in which heap 1N/A** debugging is disabled at compile time. Otherwise, a call to 1N/A** sm_malloc_x is macro expanded to a call to sm_malloc_tagged_x. 1N/A** F:sm_heap -- out of memory 1N/A** SM_MALLOC -- wrapper around malloc() 1N/A** size -- size of requested memory. 1N/A** Pointer to memory region. 1N/A** SM_REALLOC -- wrapper for realloc() 1N/A** ptr -- pointer to old memory area. 1N/A** size -- size of requested memory. 1N/A** Pointer to new memory area, NULL on failure. 1N/A** SM_REALLOC_X -- wrapper for realloc() 1N/A** ptr -- pointer to old memory area. 1N/A** size -- size of requested memory. 1N/A** Pointer to new memory area. 1N/A** F:sm_heap -- out of memory 1N/A** SM_FREE -- wrapper around free() 1N/A** ptr -- pointer to memory region. 1N/A#
else /* !SM_HEAP_CHECK */ 1N/A** Each allocated block is assigned a "group number". 1N/A** By default, all blocks are assigned to group #1. 1N/A** By convention, group #0 is for memory that is never freed. 1N/A** You can use group numbers any way you want, in order to help make 1N/A** sense of sm_heap_report output. 1N/A** Total number of bytes allocated. 1N/A** This is only maintained if the sm_check_heap debug category is active. 1N/A** High water mark: the most that SmHeapTotal has ever been. 1N/A** Maximum number of bytes that may be allocated at any one time. 1N/A** This is only honoured if sm_check_heap is active. 1N/A "@(#)$Debug: sm_heap_limit - max # of bytes permitted in heap $");
1N/A** This is the data structure that keeps track of all currently 1N/A** allocated blocks of memory known to the heap package. 1N/A** This is a randomly generated table 1N/A** which contains exactly one occurrence 1N/A** of each of the numbers between 0 and 255. 1N/A** It is used by ptrhash. 1N/A 161,
71,
77,
187,
15,
229,
9,
176,
221,
119,
239,
21,
85,
138,
203,
86,
1N/A 102,
65,
80,
199,
235,
32,
140,
96,
224,
78,
126,
127,
144, 0,
11,
179,
1N/A 64,
30,
120,
23,
225,
226,
33,
50,
205,
167,
130,
240,
174,
99,
206,
73,
1N/A 231,
210,
189,
162,
48,
93,
246,
54,
213,
141,
135,
39,
41,
192,
236,
193,
1N/A 157,
88,
95,
104,
188,
63,
133,
177,
234,
110,
158,
214,
238,
131,
233,
91,
1N/A 125,
82,
94,
79,
66,
92,
151,
45,
252,
98,
26,
183,
7,
191,
171,
106,
1N/A 145,
154,
251,
100,
113,
5,
74,
62,
76,
124,
14,
217,
200,
75,
115,
190,
1N/A 103,
28,
198,
196,
169,
219,
37,
118,
150,
18,
152,
175,
49,
136,
6,
142,
1N/A 89,
19,
243,
254,
47,
137,
24,
166,
180,
10,
40,
186,
202,
46,
184,
67,
1N/A 148,
108,
181,
81,
25,
241,
13,
139,
58,
38,
84,
253,
201,
12,
116,
17,
1N/A 195,
22,
112,
69,
255,
43,
147,
222,
111,
56,
194,
216,
149,
244,
42,
173,
1N/A 232,
220,
249,
105,
207,
51,
197,
242,
72,
211,
208,
59,
122,
230,
237,
170,
1N/A 165,
44,
68,
123,
129,
245,
143,
101,
8,
209,
215,
247,
185,
57,
218,
53,
1N/A 114,
121,
3,
128,
4,
204,
212,
146,
2,
155,
83,
250,
87,
29,
31,
159,
1N/A 60,
27,
107,
156,
227,
182,
1,
61,
36,
160,
109,
97,
90,
20,
168,
132,
1N/A 223,
248,
70,
164,
55,
172,
34,
52,
163,
117,
35,
153,
134,
16,
178,
228 1N/A** PTRHASH -- hash a pointer value 1N/A** ptrhash hashes a pointer value to a uniformly distributed random 1N/A** number between 0 and 255. 1N/A** This hash algorithm is based on Peter K. Pearson, 1N/A** "Fast Hashing of Variable-Length Text Strings", 1N/A** in Communications of the ACM, June 1990, vol 33 no 6. 1N/A if (
sizeof(
void*) ==
4 &&
sizeof(
unsigned long) ==
4)
1N/A unsigned long n = (
unsigned long)p;
1N/A else if (
sizeof(
void*) ==
8 &&
sizeof(
unsigned long) ==
8)
1N/A unsigned long n = (
unsigned long)p;
1N/A unsigned char *
cp = (
unsigned char *)&p;
1N/A for (i = 0; i <
sizeof(
void*); ++i)
1N/A** SM_MALLOC_TAGGED -- wrapper around malloc(), debugging version. 1N/A** size -- size of requested memory. 1N/A** tag -- tag for debugging. 1N/A** num -- additional value for debugging. 1N/A** group -- heap group for debugging. 1N/A** Pointer to memory region. 1N/A** SM_MALLOC_TAGGED_X -- wrapper around malloc(), debugging version. 1N/A** size -- size of requested memory. 1N/A** tag -- tag for debugging. 1N/A** num -- additional value for debugging. 1N/A** group -- heap group for debugging. 1N/A** Pointer to memory region. 1N/A** F:sm_heap -- out of memory 1N/A** SM_HEAP_REGISTER -- register a pointer into the heap for debugging. 1N/A** ptr -- pointer to register. 1N/A** size -- size of requested memory. 1N/A** tag -- tag for debugging. 1N/A** num -- additional value for debugging. 1N/A** group -- heap group for debugging. 1N/A** true iff successfully registered (not yet in table). 1N/A ** We require that ptr is not already in SmHeapTable. 1N/A sm_abort(
"sm_heap_register: ptr %p is already registered (%s:%d)",
1N/A#
endif /* SM_CHECK_REQUIRE */ 1N/A** SM_REALLOC -- wrapper for realloc(), debugging version. 1N/A** ptr -- pointer to old memory area. 1N/A** size -- size of requested memory. 1N/A** Pointer to new memory area, NULL on failure. 1N/A return NULL;
/* keep Irix compiler happy */ 1N/A** SM_REALLOC_X -- wrapper for realloc(), debugging version. 1N/A** ptr -- pointer to old memory area. 1N/A** size -- size of requested memory. 1N/A** Pointer to new memory area. 1N/A** F:sm_heap -- out of memory 1N/A return NULL;
/* keep Irix compiler happy */ 1N/A** SM_FREE_TAGGED -- wrapper around free(), debugging version. 1N/A** ptr -- pointer to memory region. 1N/A** tag -- tag for debugging. 1N/A** num -- additional value for debugging. 1N/A ** Fill the block with zeros before freeing. 1N/A ** This is intended to catch problems with 1N/A ** dangling pointers. The block is filled with 1N/A ** zeros, not with some non-zero value, because 1N/A ** it is common practice in some C code to store 1N/A ** a zero in a structure member before freeing the 1N/A ** structure, as a defense against dangling pointers. 1N/A** SM_HEAP_CHECKPTR_TAGGED -- check whether ptr is a valid argument to sm_free 1N/A** ptr -- pointer to memory region. 1N/A** tag -- tag for debugging. 1N/A** num -- additional value for debugging. 1N/A** aborts if check fails. 1N/A** SM_HEAP_REPORT -- output "map" of used heap. 1N/A** stream -- the file pointer to write to. 1N/A** verbosity -- how much info? 1N/A "%4d %*lx %7lu bytes",
1N/A (
int)
sizeof(
void *) *
2,
1N/A "heap max=%lu, total=%lu, ",
1N/A "group 0=%lu, group 1=%lu, others=%lu\n",
1N/A "BUG => SmHeapTotal: got %lu, expected %lu\n",
1N/A#
endif /* !SM_HEAP_CHECK */