Newsgroups: comp.lang.c

In comp.lang.c, wkaufman@us.oracle.com (William Kaufman) writes:

> In article <chuckb.713052667@milton> chuckb@milton.u.washington.edu (Chuck Bass) writes:

> ] Why is there such a (perceived) resistance to dynamic memory
> ] allocation?  It's really nice once you get used to cleaning up
> ] after yourself.

>     The only problems with it are that malloc() and free() may be
> expensive, and you might forget to free the memory.  And, to answer
> another line here, it *isn't* guaranteed that the memory will be freed
> on exit: there are still OSes out there that *don't* reclaim memory on
> exit (True!).

>   But, of course, malloc() may be necessary if you expect the value to
> last: globals can't be overwritten, and local variables disappear.

I personally avoid malloc() when writing reusable libraries since
I have no control of the application used with them and how that
application uses dynamic memory or which allocation strategies and
algorithms will be used.  Not that malloc() is a BAD THING - but it
can be troublesome.

For example, a fairly simple Motif program I checked called
malloc+calloc+realloc+free about 13000 times (no typo) before "coming up"
and *most* of these calls were in various X toolkit routines - not
for the direct benefit of the application program.  Adding a relatively
simple dialog box was about another 2500 calls.  This is probably
indicative of a suboptimal design.  In any case, any initial heap
"locality" will be lost in these programs and operations touching several
dynamic chunks of memory will eventually cause excessive paging regardless
of how good the allocator may be.  This boils down to "malloc may be
slow" and since I want my library to be fast, I avoid malloc if reasonable.

The best alternative to malloc() is of course local variables - where
possible.  The stack mechanism - being intertwined with the program
control flow - has all the right information about when to allocate
and free memory and "fragmentation" never occurs.

Two things typically demand dynamic memory - persistant data and
variable-size data.  An example of the latter is, say, a function
which packs a vector of strings (like argv[]) into a single string.
Since the final size is unknown, dynamic allocation must be used.  Some
folks are lucky enough to be able to use alloca() which does on-stack
allocation and is probably the best solution to this problem.  Another
one which I often use, is to include a local buffer variable in hopes
it will be "big enough" in most cases.  In cases where it is too small
I have to call malloc().  This works extremely well in many cases..
For example, in screen-oriented applications, a buffer of ~80 bytes
would be sufficient to hold most strings.

The other case, requiring data to be persistant beyond the function
invocation, *demands* dynamic memory allocation and is probably
the reason Xt applications batter dynamic memory so much.  Many modern
"event-driven" applications use the "callback" architecture.  Retention
of state and data between callback invocations and between separate callbacks
requires dynamic (or global) memory.  Saving an integer or pointer,
a relatively common occurance, results in allocating 4 bytes which is
often quite wasteful - it's also common in Xt applications.  

Luckily the callback/Xt situation may improve over time.  "Callback"
applications are merely multi-threaded applications without any thread
"support" like per-thread stacks and program counters.  With per-thread
stacks, most of the malloc()s demanded by callbacks would probably be
replaced with local variables - and as stated before, the stack is a very
simple and efficient allocation mechanism.  Stacks also cluster related data
together - reducing paging demands.

IMO, the moral of all this is that many "modern" applications so badly
abuse dynamic memory that it is *currently* good to avoid it when
reasonable.  Copious calls to dynamic memory functions are sometimes an
indicator of suboptimal architecture (e.g., window toolkits should probably
use real threads).


	    -Paul Bame
	    bame@hubble.sde.hp.com	N0KCL