]> git.sur5r.net Git - bacula/docs/blob - docs/developers/smartall.tex
Final changes
[bacula/docs] / docs / developers / smartall.tex
1 %%
2 %%
3
4 \addcontentsline{lof}{figure}{Smart Memory Allocation with Orphaned Buffer
5 Detection}
6 \includegraphics{./smartall.eps} 
7
8 \section*{Smart Memory Allocation With Orphaned Buffer Detection }
9 \label{_ChapterStart4}
10 \index{Detection!Smart Memory Allocation With Orphaned Buffer }
11 \index{Smart Memory Allocation With Orphaned Buffer Detection }
12 \addcontentsline{toc}{section}{Smart Memory Allocation With Orphaned Buffer
13 Detection}
14
15
16 Few things are as embarrassing as a program that leaks, yet few errors are so
17 easy to commit or as difficult to track down in a large, complicated program
18 as failure to release allocated memory. SMARTALLOC replaces the standard C
19 library memory allocation functions with versions which keep track of buffer
20 allocations and releases and report all orphaned buffers at the end of program
21 execution. By including this package in your program during development and
22 testing, you can identify code that loses buffers right when it's added and
23 most easily fixed, rather than as part of a crisis debugging push when the
24 problem is identified much later in the testing cycle (or even worse, when the
25 code is in the hands of a customer). When program testing is complete, simply
26 recompiling with different flags removes SMARTALLOC from your program,
27 permitting it to run without speed or storage penalties. 
28
29 In addition to detecting orphaned buffers, SMARTALLOC also helps to find other
30 common problems in management of dynamic storage including storing before the
31 start or beyond the end of an allocated buffer, referencing data through a
32 pointer to a previously released buffer, attempting to release a buffer twice
33 or releasing storage not obtained from the allocator, and assuming the initial
34 contents of storage allocated by functions that do not guarantee a known
35 value. SMARTALLOC's checking does not usually add a large amount of overhead
36 to a program (except for programs which use {\tt realloc()} extensively; see
37 below). SMARTALLOC focuses on proper storage management rather than internal
38 consistency of the heap as checked by the malloc\_debug facility available on
39 some systems. SMARTALLOC does not conflict with malloc\_debug and both may be
40 used together, if you wish. SMARTALLOC makes no assumptions regarding the
41 internal structure of the heap and thus should be compatible with any C
42 language implementation of the standard memory allocation functions. 
43
44 \subsubsection*{ Installing SMARTALLOC}
45 \index{SMARTALLOC!Installing }
46 \index{Installing SMARTALLOC }
47 \addcontentsline{toc}{subsubsection}{Installing SMARTALLOC}
48
49 SMARTALLOC is provided as a Zipped archive, 
50 \elink{smartall.zip}{http://www.fourmilab.ch/smartall/smartall.zip}; see the
51 download instructions below. 
52
53 To install SMARTALLOC in your program, simply add the statement: 
54
55 to every C program file which calls any of the memory allocation functions
56 ({\tt malloc}, {\tt calloc}, {\tt free}, etc.). SMARTALLOC must be used for
57 all memory allocation with a program, so include file for your entire program,
58 if you have such a thing. Next, define the symbol SMARTALLOC in the
59 compilation before the inclusion of smartall.h. I usually do this by having my
60 Makefile add the ``{\tt -DSMARTALLOC}'' option to the C compiler for
61 non-production builds. You can define the symbol manually, if you prefer, by
62 adding the statement: 
63
64 {\tt \#define SMARTALLOC} 
65
66 At the point where your program is all done and ready to relinquish control to
67 the operating system, add the call: 
68
69 {\tt \ \ \ \ \ \ \ \ sm\_dump(}{\it datadump}{\tt );} 
70
71 where {\it datadump} specifies whether the contents of orphaned buffers are to
72 be dumped in addition printing to their size and place of allocation. The data
73 are dumped only if {\it datadump} is nonzero, so most programs will normally
74 use ``{\tt sm\_dump(0);}''. If a mysterious orphaned buffer appears that can't
75 be identified from the information this prints about it, replace the statement
76 with ``{\tt sm\_dump(1)};''. Usually the dump of the buffer's data will
77 furnish the additional clues you need to excavate and extirpate the elusive
78 error that left the buffer allocated. 
79
80 Finally, add the files ``smartall.h'' and ``smartall.c'' from this release to
81 your source directory, make dependencies, and linker input. You needn't make
82 inclusion of smartall.c in your link optional; if compiled with SMARTALLOC not
83 defined it generates no code, so you may always include it knowing it will
84 waste no storage in production builds. Now when you run your program, if it
85 leaves any buffers around when it's done, each will be reported by {\tt
86 sm\_dump()} on stderr as follows: 
87
88 \footnotesize
89 \begin{verbatim}
90 Orphaned buffer:     120 bytes allocated at line 50 of gutshot.c
91 \end{verbatim}
92 \normalsize
93
94 \subsubsection*{ Squelching a SMARTALLOC}
95 \index{SMARTALLOC!Squelching a }
96 \index{Squelching a SMARTALLOC }
97 \addcontentsline{toc}{subsubsection}{Squelching a SMARTALLOC}
98
99 Usually, when you first install SMARTALLOC in an existing program you'll find
100 it nattering about lots of orphaned buffers. Some of these turn out to be
101 legitimate errors, but some are storage allocated during program
102 initialisation that, while dynamically allocated, is logically static storage
103 not intended to be released. Of course, you can get rid of the complaints
104 about these buffers by adding code to release them, but by doing so you're
105 adding unnecessary complexity and code size to your program just to silence
106 the nattering of a SMARTALLOC, so an escape hatch is provided to eliminate the
107 need to release these buffers. 
108
109 Normally all storage allocated with the functions {\tt malloc()}, {\tt
110 calloc()}, and {\tt realloc()} is monitored by SMARTALLOC. If you make the
111 function call: 
112
113 \footnotesize
114 \begin{verbatim}
115         sm_static(1);
116 \end{verbatim}
117 \normalsize
118
119 you declare that subsequent storage allocated by {\tt malloc()}, {\tt
120 calloc()}, and {\tt realloc()} should not be considered orphaned if found to
121 be allocated when {\tt sm\_dump()} is called. I use a call on ``{\tt
122 sm\_static(1);}'' before I allocate things like program configuration tables
123 so I don't have to add code to release them at end of program time. After
124 allocating unmonitored data this way, be sure to add a call to: 
125
126 \footnotesize
127 \begin{verbatim}
128         sm_static(0);
129 \end{verbatim}
130 \normalsize
131
132 to resume normal monitoring of buffer allocations. Buffers allocated while
133 {\tt sm\_static(1}) is in effect are not checked for having been orphaned but
134 all the other safeguards provided by SMARTALLOC remain in effect. You may
135 release such buffers, if you like; but you don't have to. 
136
137 \subsubsection*{ Living with Libraries}
138 \index{Libraries!Living with }
139 \index{Living with Libraries }
140 \addcontentsline{toc}{subsubsection}{Living with Libraries}
141
142 Some library functions for which source code is unavailable may gratuitously
143 allocate and return buffers that contain their results, or require you to pass
144 them buffers which they subsequently release. If you have source code for the
145 library, by far the best approach is to simply install SMARTALLOC in it,
146 particularly since this kind of ill-structured dynamic storage management is
147 the source of so many storage leaks. Without source code, however, there's no
148 option but to provide a way to bypass SMARTALLOC for the buffers the library
149 allocates and/or releases with the standard system functions. 
150
151 For each function {\it xxx} redefined by SMARTALLOC, a corresponding routine
152 named ``{\tt actually}{\it xxx}'' is furnished which provides direct access to
153 the underlying system function, as follows: 
154
155 \begin{quote}
156
157 \begin{longtable}{ll}
158 \multicolumn{1}{l }{\bf Standard function } & \multicolumn{1}{l }{\bf Direct
159 access function  } \\
160 {{\tt malloc(}{\it size}{\tt )}  } & {{\tt actuallymalloc(}{\it size}{\tt )} 
161 } \\
162 {{\tt calloc(}{\it nelem}{\tt ,} {\it elsize}{\tt )}  } & {{\tt
163 actuallycalloc(}{\it nelem}, {\it elsize}{\tt )}   } \\
164 {{\tt realloc(}{\it ptr}{\tt ,} {\it size}{\tt )} } & {{\tt
165 actuallyrealloc(}{\it ptr}, {\it size}{\tt )}  } \\
166 {{\tt free(}{\it ptr}{\tt )} } & {{\tt actuallyfree(}{\it ptr}{\tt )} }
167
168 \end{longtable}
169
170 \end{quote}
171
172 For example, suppose there exists a system library function named ``{\tt
173 getimage()}'' which reads a raster image file and returns the address of a
174 buffer containing it. Since the library routine allocates the image directly
175 with {\tt malloc()}, you can't use SMARTALLOC's {\tt free()}, as that call
176 expects information placed in the buffer by SMARTALLOC's special version of
177 {\tt malloc()}, and hence would report an error. To release the buffer you
178 should call {\tt actuallyfree()}, as in this code fragment: 
179
180 \footnotesize
181 \begin{verbatim}
182         struct image *ibuf = getimage("ratpack.img");
183         display_on_screen(ibuf);
184         actuallyfree(ibuf);
185 \end{verbatim}
186 \normalsize
187
188 Conversely, suppose we are to call a library function, ``{\tt putimage()}'',
189 which writes an image buffer into a file and then releases the buffer with
190 {\tt free()}. Since the system {\tt free()} is being called, we can't pass a
191 buffer allocated by SMARTALLOC's allocation routines, as it contains special
192 information that the system {\tt free()} doesn't expect to be there. The
193 following code uses {\tt actuallymalloc()} to obtain the buffer passed to such
194 a routine. 
195
196 \footnotesize
197 \begin{verbatim}
198         struct image *obuf =
199            (struct image *) actuallymalloc(sizeof(struct image));
200         dump_screen_to_image(obuf);
201         putimage("scrdump.img", obuf);  /* putimage() releases obuf */
202 \end{verbatim}
203 \normalsize
204
205 It's unlikely you'll need any of the ``actually'' calls except under very odd
206 circumstances (in four products and three years, I've only needed them once),
207 but they're there for the rare occasions that demand them. Don't use them to
208 subvert the error checking of SMARTALLOC; if you want to disable orphaned
209 buffer detection, use the {\tt sm\_static(1)} mechanism described above. That
210 way you don't forfeit all the other advantages of SMARTALLOC as you do when
211 using {\tt actuallymalloc()} and {\tt actuallyfree()}. 
212
213 \subsubsection*{ SMARTALLOC Details}
214 \index{SMARTALLOC Details }
215 \index{Details!SMARTALLOC }
216 \addcontentsline{toc}{subsubsection}{SMARTALLOC Details}
217
218 When you include ``smartall.h'' and define SMARTALLOC, the following standard
219 system library functions are redefined with the \#define mechanism to call
220 corresponding functions within smartall.c instead. (For details of the
221 redefinitions, please refer to smartall.h.) 
222
223 \footnotesize
224 \begin{verbatim}
225         void *malloc(size_t size)
226         void *calloc(size_t nelem, size_t elsize)
227         void *realloc(void *ptr, size_t size)
228         void free(void *ptr)
229         void cfree(void *ptr)
230 \end{verbatim}
231 \normalsize
232
233 {\tt cfree()} is a historical artifact identical to {\tt free()}. 
234
235 In addition to allocating storage in the same way as the standard library
236 functions, the SMARTALLOC versions expand the buffers they allocate to include
237 information that identifies where each buffer was allocated and to chain all
238 allocated buffers together. When a buffer is released, it is removed from the
239 allocated buffer chain. A call on {\tt sm\_dump()} is able, by scanning the
240 chain of allocated buffers, to find all orphaned buffers. Buffers allocated
241 while {\tt sm\_static(1)} is in effect are specially flagged so that, despite
242 appearing on the allocated buffer chain, {\tt sm\_dump()} will not deem them
243 orphans. 
244
245 When a buffer is allocated by {\tt malloc()} or expanded with {\tt realloc()},
246 all bytes of newly allocated storage are set to the hexadecimal value 0x55
247 (alternating one and zero bits). Note that for {\tt realloc()} this applies
248 only to the bytes added at the end of buffer; the original contents of the
249 buffer are not modified. Initializing allocated storage to a distinctive
250 nonzero pattern is intended to catch code that erroneously assumes newly
251 allocated buffers are cleared to zero; in fact their contents are random. The
252 {\tt calloc()} function, defined as returning a buffer cleared to zero,
253 continues to zero its buffers under SMARTALLOC. 
254
255 Buffers obtained with the SMARTALLOC functions contain a special sentinel byte
256 at the end of the user data area. This byte is set to a special key value
257 based upon the buffer's memory address. When the buffer is released, the key
258 is tested and if it has been overwritten an assertion in the {\tt free}
259 function will fail. This catches incorrect program code that stores beyond the
260 storage allocated for the buffer. At {\tt free()} time the queue links are
261 also validated and an assertion failure will occur if the program has
262 destroyed them by storing before the start of the allocated storage. 
263
264 In addition, when a buffer is released with {\tt free()}, its contents are
265 immediately destroyed by overwriting them with the hexadecimal pattern 0xAA
266 (alternating bits, the one's complement of the initial value pattern). This
267 will usually trip up code that keeps a pointer to a buffer that's been freed
268 and later attempts to reference data within the released buffer. Incredibly,
269 this is {\it legal} in the standard Unix memory allocation package, which
270 permits programs to free() buffers, then raise them from the grave with {\tt
271 realloc()}. Such program ``logic'' should be fixed, not accommodated, and
272 SMARTALLOC brooks no such Lazarus buffer`` nonsense. 
273
274 Some C libraries allow a zero size argument in calls to {\tt malloc()}. Since
275 this is far more likely to indicate a program error than a defensible
276 programming stratagem, SMARTALLOC disallows it with an assertion. 
277
278 When the standard library {\tt realloc()} function is called to expand a
279 buffer, it attempts to expand the buffer in place if possible, moving it only
280 if necessary. Because SMARTALLOC must place its own private storage in the
281 buffer and also to aid in error detection, its version of {\tt realloc()}
282 always moves and copies the buffer except in the trivial case where the size
283 of the buffer is not being changed. By forcing the buffer to move on every
284 call and destroying the contents of the old buffer when it is released,
285 SMARTALLOC traps programs which keep pointers into a buffer across a call on
286 {\tt realloc()} which may move it. This strategy may prove very costly to
287 programs which make extensive use of {\tt realloc()}. If this proves to be a
288 problem, such programs may wish to use {\tt actuallymalloc()}, {\tt
289 actuallyrealloc()}, and {\tt actuallyfree()} for such frequently-adjusted
290 buffers, trading error detection for performance. Although not specified in
291 the System V Interface Definition, many C library implementations of {\tt
292 realloc()} permit an old buffer argument of NULL, causing {\tt realloc()} to
293 allocate a new buffer. The SMARTALLOC version permits this. 
294
295 \subsubsection*{ When SMARTALLOC is Disabled}
296 \index{When SMARTALLOC is Disabled }
297 \index{Disabled!When SMARTALLOC is }
298 \addcontentsline{toc}{subsubsection}{When SMARTALLOC is Disabled}
299
300 When SMARTALLOC is disabled by compiling a program with the symbol SMARTALLOC
301 not defined, calls on the functions otherwise redefined by SMARTALLOC go
302 directly to the system functions. In addition, compile-time definitions
303 translate calls on the ''{\tt actually}...{\tt ()}`` functions into the
304 corresponding library calls; ''{\tt actuallymalloc(100)}``, for example,
305 compiles into ''{\tt malloc(100)}``. The two special SMARTALLOC functions,
306 {\tt sm\_dump()} and {\tt sm\_static()}, are defined to generate no code
307 (hence the null statement). Finally, if SMARTALLOC is not defined, compilation
308 of the file smartall.c generates no code or data at all, effectively removing
309 it from the program even if named in the link instructions. 
310
311 Thus, except for unusual circumstances, a program that works with SMARTALLOC
312 defined for testing should require no changes when built without it for
313 production release. 
314
315 \subsubsection*{ The {\tt alloc()} Function}
316 \index{Function!alloc }
317 \index{Alloc() Function }
318 \addcontentsline{toc}{subsubsection}{alloc() Function}
319
320 Many programs I've worked on use very few direct calls to {\tt malloc()},
321 using the identically declared {\tt alloc()} function instead. Alloc detects
322 out-of-memory conditions and aborts, removing the need for error checking on
323 every call of {\tt malloc()} (and the temptation to skip checking for
324 out-of-memory). 
325
326 As a convenience, SMARTALLOC supplies a compatible version of {\tt alloc()} in
327 the file alloc.c, with its definition in the file alloc.h. This version of
328 {\tt alloc()} is sensitive to the definition of SMARTALLOC and cooperates with
329 SMARTALLOC's orphaned buffer detection. In addition, when SMARTALLOC is
330 defined and {\tt alloc()} detects an out of memory condition, it takes
331 advantage of the SMARTALLOC diagnostic information to identify the file and
332 line number of the call on {\tt alloc()} that failed. 
333
334 \subsubsection*{ Overlays and Underhandedness}
335 \index{Underhandedness!Overlays and }
336 \index{Overlays and Underhandedness }
337 \addcontentsline{toc}{subsubsection}{Overlays and Underhandedness}
338
339 String constants in the C language are considered to be static arrays of
340 characters accessed through a pointer constant. The arrays are potentially
341 writable even though their pointer is a constant. SMARTALLOC uses the
342 compile-time definition {\tt ./smartall.wml} to obtain the name of the file in
343 which a call on buffer allocation was performed. Rather than reserve space in
344 a buffer to save this information, SMARTALLOC simply stores the pointer to the
345 compiled-in text of the file name. This works fine as long as the program does
346 not overlay its data among modules. If data are overlayed, the area of memory
347 which contained the file name at the time it was saved in the buffer may
348 contain something else entirely when {\tt sm\_dump()} gets around to using the
349 pointer to edit the file name which allocated the buffer. 
350
351 If you want to use SMARTALLOC in a program with overlayed data, you'll have to
352 modify smartall.c to either copy the file name to a fixed-length field added
353 to the {\tt abufhead} structure, or else allocate storage with {\tt malloc()},
354 copy the file name there, and set the {\tt abfname} pointer to that buffer,
355 then remember to release the buffer in {\tt sm\_free}. Either of these
356 approaches are wasteful of storage and time, and should be considered only if
357 there is no alternative. Since most initial debugging is done in non-overlayed
358 environments, the restrictions on SMARTALLOC with data overlaying may never
359 prove a problem. Note that conventional overlaying of code, by far the most
360 common form of overlaying, poses no problems for SMARTALLOC; you need only be
361 concerned if you're using exotic tools for data overlaying on MS-DOS or other
362 address-space-challenged systems. 
363
364 Since a C language ''constant`` string can actually be written into, most C
365 compilers generate a unique copy of each string used in a module, even if the
366 same constant string appears many times. In modules that contain many calls on
367 allocation functions, this results in substantial wasted storage for the
368 strings that identify the file name. If your compiler permits optimization of
369 multiple occurrences of constant strings, enabling this mode will eliminate
370 the overhead for these strings. Of course, it's up to you to make sure
371 choosing this compiler mode won't wreak havoc on some other part of your
372 program. 
373
374 \subsubsection*{ Test and Demonstration Program}
375 \index{Test and Demonstration Program }
376 \index{Program!Test and Demonstration }
377 \addcontentsline{toc}{subsubsection}{Test and Demonstration Program}
378
379 A test and demonstration program, smtest.c, is supplied with SMARTALLOC. You
380 can build this program with the Makefile included. Please refer to the
381 comments in smtest.c and the Makefile for information on this program. If
382 you're attempting to use SMARTALLOC on a new machine or with a new compiler or
383 operating system, it's a wise first step to check it out with smtest first. 
384
385 \subsubsection*{ Invitation to the Hack}
386 \index{Hack!Invitation to the }
387 \index{Invitation to the Hack }
388 \addcontentsline{toc}{subsubsection}{Invitation to the Hack}
389
390 SMARTALLOC is not intended to be a panacea for storage management problems,
391 nor is it universally applicable or effective; it's another weapon in the
392 arsenal of the defensive professional programmer attempting to create reliable
393 products. It represents the current state of evolution of expedient debug code
394 which has been used in several commercial software products which have,
395 collectively, sold more than third of a million copies in the retail market,
396 and can be expected to continue to develop through time as it is applied to
397 ever more demanding projects. 
398
399 The version of SMARTALLOC here has been tested on a Sun SPARCStation, Silicon
400 Graphics Indigo2, and on MS-DOS using both Borland and Microsoft C. Moving
401 from compiler to compiler requires the usual small changes to resolve disputes
402 about prototyping of functions, whether the type returned by buffer allocation
403 is {\tt char\ *} or {\tt void\ *}, and so forth, but following those changes
404 it works in a variety of environments. I hope you'll find SMARTALLOC as useful
405 for your projects as I've found it in mine. 
406
407 \subsection*{
408 \elink{}{http://www.fourmilab.ch/smartall/smartall.zip} 
409 \elink{Download smartall.zip}{http://www.fourmilab.ch/smartall/smartall.zip}
410 (Zipped archive)}
411 \index{Archive! Download smartall.zip Zipped }
412 \index{ Download smartall.zip (Zipped archive) }
413 \addcontentsline{toc}{subsection}{ Download smartall.zip (Zipped archive)}
414
415 SMARTALLOC is provided as 
416 \elink{smartall.zip}{http://www.fourmilab.ch/smartall/smartall.zip}, a  
417 \elink{Zipped}{http://www.pkware.com/} archive containing  source code,
418 documentation, and a  {\tt Makefile} to build the software under Unix. 
419
420 \subsubsection*{ Copying}
421 \index{Copying }
422 \addcontentsline{toc}{subsubsection}{Copying}
423
424 \begin{quote}
425 SMARTALLOC is in the public domain. Permission to use, copy, modify, and
426 distribute this software and its documentation for any purpose and without fee
427 is hereby granted, without any conditions or restrictions. This software is
428 provided ''as is`` without express or implied warranty. 
429 \end{quote}
430
431 {\it 
432 \elink{by John Walker}{http://www.fourmilab.ch}
433 October 30th, 1998 }