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