Living with Libraries

Some library functions for which source code is unavailable may gratuitously allocate and return buffers that contain their results, or require you to pass them buffers which they subsequently release. If you have source code for the library, by far the best approach is to simply install SMARTALLOC in it, particularly since this kind of ill-structured dynamic storage management is the source of so many storage leaks. Without source code, however, there’s no option but to provide a way to bypass SMARTALLOC for the buffers the library allocates and/or releases with the standard system functions.

For each function xxx redefined by SMARTALLOC, a corresponding routine named “actuallyxxx” is furnished which provides direct access to the underlying system function, as follows:

Table 17.1: Systems functions

Standard function

Direct access function

malloc(size)

actuallymalloc(size)

calloc(nelem,elsize)

actuallycalloc(nelem,elsize)

realloc(ptr,size)

actuallyrealloc(ptr,size)

free(ptr)

actuallyfree(ptr)

For example, suppose there exists a system library function named “getimage()” which reads a raster image file and returns the address of a buffer containing it. Since the library routine allocates the image directly with malloc(), you can’t use SMARTALLOC’s free(), as that call expects information placed in the buffer by SMARTALLOC’s special version of malloc(), and hence would report an error. To release the buffer you should call actuallyfree(), as in this code fragment:

struct image *ibuf = getimage("ratpack.img");
display_on_screen(ibuf);
actuallyfree(ibuf);

Conversely, suppose we are to call a library function, “putimage()”, which writes an image buffer into a file and then releases the buffer with free(). Since the system free() is being called, we can’t pass a buffer allocated by SMARTALLOC’s allocation routines, as it contains special information that the system free() doesn’t expect to be there. The following code uses actuallymalloc() to obtain the buffer passed to such a routine.

struct image *obuf =
   (struct image *) actuallymalloc(sizeof(struct image));
dump_screen_to_image(obuf);
putimage("scrdump.img", obuf);  /* putimage() releases obuf */

It’s unlikely you’ll need any of the “actually” calls except under very odd circumstances (in four products and three years, I’ve only needed them once), but they’re there for the rare occasions that demand them. Don’t use them to subvert the error checking of SMARTALLOC; if you want to disable orphaned buffer detection, use the sm_static(1) mechanism described above. That way you don’t forfeit all the other advantages of SMARTALLOC as you do when using actuallymalloc() and actuallyfree().

Possible Next Steps

Go back to Smart Memory Allocation.

Go back to Developer Guide.