A lazy memory manager strategy

J

jacob navia

One of the less known memory management strategy is the lazy one:

Allocate all you need and never bother to free.
Rely on the operating system cleaning up for you
when your program exits.

It has two big advantages:
Fast (no free)
Simple (no free and related bugs)

In programs that are transient (a compiler for instance)
this is a winning mixture.

In lcc-win, all the global context must be present until the last
line of the program is compiled, and even later, when
supplying some context to the assembler.

The strategy is then to just allocate memory and forget
about the few free() that could be done here and there.

Many programs are transient. Utilities, filters, and could
benefit from this simple way of memory management.

In certain cases of course, memory consumption *could*
be a problem, but in *many* cases it isn't at all important.

Recently, some people expressed disbelief at this attitude
but I think it is perfectly correct.

Each program is different to others, and a lazy memory
management is the best for many of them. The operating system
becomes the garbage collector for free!
 
R

Richard Heathfield

jacob navia said:
One of the less known memory management strategy is the lazy one:

Allocate all you need and never bother to free.
Rely on the operating system cleaning up for you
when your program exits.

Whether the OS cleans up after you is beyond the purview of the C Standard.

Your preferred memory management "strategy" comes as no surprise. It's
exactly what I would have expected you to do.

Recently, some people expressed disbelief at this attitude

Oh, I don't disbelieve it at all.
but I think it is perfectly correct.

I agree that you think it is perfectly correct.

<snip>
 
I

Ian Collins

jacob said:
One of the less known memory management strategy is the lazy one:

Allocate all you need and never bother to free.
Rely on the operating system cleaning up for you
when your program exits.

It has two big advantages:
Fast (no free)
Simple (no free and related bugs)

In programs that are transient (a compiler for instance)
this is a winning mixture.
What if the application allocates even modest amounts of memory in a
frequently called function? Maybe not a big deal on a single user
system with sufficient resources, but very antisocial on a multi-user
system.
In lcc-win, all the global context must be present until the last
line of the program is compiled, and even later, when
supplying some context to the assembler.
That case is the exception rather than the rule. Also consider the case
of a parallel build system which invokes multiple instances of the compiler.
The strategy is then to just allocate memory and forget
about the few free() that could be done here and there.

Many programs are transient. Utilities, filters, and could
benefit from this simple way of memory management.

In certain cases of course, memory consumption *could*
be a problem, but in *many* cases it isn't at all important.
The very existence of the word could in the above makes it a bad idea.
Recently, some people expressed disbelief at this attitude
but I think it is perfectly correct.
It's a sloppy practice that might be valid in a few rare cases, but it
should not be recommended to beginners, who should learn to clean up
after themselves.
 
J

jacob navia

Ian said:
What if the application allocates even modest amounts of memory in a
frequently called function? Maybe not a big deal on a single user
system with sufficient resources, but very antisocial on a multi-user
system.

It depends. Many transient programs just process the input data
(and make many allocations), then produce some output
(when they *could* do some free()s) and then exit.

Why bother?
That case is the exception rather than the rule. Also consider the case
of a parallel build system which invokes multiple instances of the compiler.

That would be the same if I did a few free() here and there
anyway!

Most of the global context needs to be there anyway
#defines
definitions
etc
It's a sloppy practice that might be valid in a few rare cases, but it
should not be recommended to beginners, who should learn to clean up
after themselves.

Or use the GC!
The lazy strategy is source compatible with the GC!

:)

It only uses the OS as GC.
 
R

Richard Heathfield

jacob navia said:

Many transient programs just process the input data
(and make many allocations), then produce some output
(when they *could* do some free()s) and then exit.

Why bother?

All right, I've explained this before in clc, but Mr Navia obviously can't
remember that far back, so I'll explain it one more time.

Once upon a time, there was an insurance quotations system. It was a
standalone program written in ISO C (except for the database module, which
existed in two separate versions, one for the mainframe and one for the
PC, and that module is irrelevant to this explanation).

This program (which I did not write, I hasten to add! I was involved in
testing it, though) allocated very large amounts of memory, none of which
was freed. The - the... well, the *person* <cough> who was responsible for
this "design decision" reasoned in the same way as you do that it was a
waste of time to do proper housekeeping.

Time moved on, as it always does. Approximately five years later, a
significantly larger system was being developed, and it turned out that
the older system had exactly the functionality required by one of the
modules of the new system. All we had to do was rename main() to foo(),
and then call foo()... in a loop.

I presume you can guess what happened. The program leaked memory like a
sieve, and nothing could run to completion because there simply weren't
enough bytes to spare.

The cost of retrofitting the free() housekeeping *far* exceeded the cost
that would have been incurred by putting it in place when the code was
originally written.

I know from experience that Mr Navia rarely if ever bothers to listen to
good advice, so I won't try to persuade him. But for anyone else out there
- failing to free up your memory allocations when you no longer need them
is *not* an intelligent programming strategy, but an unprofessional lack
of due diligence.
 
W

Wade Ward

Windows typically gives you two gigs to hang yourself with.
It depends. Many transient programs just process the input data
(and make many allocations), then produce some output
(when they *could* do some free()s) and then exit.

Why bother?


That would be the same if I did a few free() here and there
anyway!

Most of the global context needs to be there anyway
#defines
definitions
etc
There are also circumstances when you *want* memory to leak from a certain
perspective. Your constructor can be in C, so that memory requested is
explicit; the task can be linked; cleanup in another syntax or done by the
OS.
 
R

rosewater

jacob said:
One of the less known memory management strategy is the lazy one:

Allocate all you need and never bother to free.
Rely on the operating system cleaning up for you
when your program exits.

Not sure "strategy" is quite the right word here...

It won't even always work: several versions of MS-DOS do not release
all non-free()d memory on program termination.
In programs that are transient (a compiler for instance)
this is a winning mixture.

It's interesting. You don't release the source code to lcc-win32,
leaving people to guess what a great big stinking pile of shit it must
be under the hood. But I'd certainly have given you credit for
managing memory, at least at a schoolboy level. Now you reveal that
you've even screwed up in that simplest aspect of C programming.
Recently, some people expressed disbelief at this attitude
but I think it is perfectly correct.

It's hard to tell whether you are being serious, or trying (as usual)
to get a rise out of Mr. Heathfield. Can anyone *really* be that
stupid?? Guess so.
 
S

Spiros Bousbouras

Not sure "strategy" is quite the right word here...

It won't even always work: several versions of MS-DOS do not release
all non-free()d memory on program termination.

Although this is out of topic it peaked my curiosity.
Which versions of MS-DOS ? Is there a rationale for such
a decision ?
 
C

cr88192

Spiros Bousbouras said:
Although this is out of topic it peaked my curiosity.
Which versions of MS-DOS ? Is there a rationale for such
a decision ?

I had before thought it was all of them (the rational being 'because it was
DOS'...), but, then again, if I was wrong, that is interesting to note...

I am not sure, I don't think Win3x (or maybe even Win95) correctly freed
memory on exit, but, I don't know with any real certainty...

all I really do know is that linux and properly process-based windows (NT,
2000, XP, Vista) do this as the natural behavior (I think Win95, and maybe
also 98 or Me, put all the running apps in a single big address space, but
then again, I am not certain on this point either, as I have never really
looked into this).

or such...
 
C

CBFalconer

cr88192 said:
.... snip ...

I had before thought it was all of them (the rational being
'because it was DOS'...), but, then again, if I was wrong, that
is interesting to note...

I am not sure, I don't think Win3x (or maybe even Win95) correctly
freed memory on exit, but, I don't know with any real certainty...

DOS couldn't. A standard practice was to allocate memory for a
permanently allocated subsystem (a TSR), and retain that memory on
exit. Many people got fouled by allocating too much (so nothing
more was available until a reboot) or too little (so the TSR didn't
work).
 
D

Don Morris

jacob said:
One of the less known memory management strategy is the lazy one:

Allocate all you need and never bother to free.
Rely on the operating system cleaning up for you
when your program exits.

It has two big advantages:
Fast (no free)
Simple (no free and related bugs)

[Yes, this seems to me to be entirely OffTopic for the group -
sorry that I feel compelled to reply here. The OnTopic version
of a reply to this would, of course, be that the implementation
isn't guaranteed to do anything for you of the sort.. so you
can't rely on it in portable code (or in all implementations)].

And a few big disadvantages.

First -- your lack of garbage collection / reliance on the OS
may suffice for backing physical memory (you can assume not
only will the OS clean up after you, but that it will likely
do LRU or other cleanup if resources are needed elsewhere
via page reclamation anyway). You're completely ignoring
virtual addressing constraints, however -- which 32-bit
programs [still very prevalent] are hitting even with
proper memory management. If your 32-bit simple process
is on a platform that only gives 1Gb of total private
data space, for example... what happens after the 8th
call to a function that malloc()'s a 128Mb buffer to
process some data read in from I/O, then written back
out if you skip the free()? That's right... you'll get
a malloc() failure... for no good reason.

Second -- some platforms have a cost to virtual address space
allocation (swap pre-reservation, like HP-UX). If you never
free() anything back... even your simple programs during
runtime suddenly consumes more reservation resources... which
means you can run less of them at a time. The system space
experiences a regression in throughput/processing.

Third -- When you allocate *more* space from the underlying
OS (and then instantiate it, either at allocation time or
on access time in a virtual memory system via fault), you
are always going to have that instantiation cost. If you
free() back memory (to the OS or a memory management layer
between you [like libc]), that memory can be cached and
reused... which is likely much faster than going all the
way down the allocation stack in the OS. (Which means that
one of your advantages.... likely isn't).

In most implementations, free() is fairly fast and cheap.
If you encounter an implementation where it is not... that
seems like an excellent discussion to have with the
implementation maintainers. I'm unconvinced that the
disadvantages noted above don't outweigh your purported
benefits -- since it is likely:

+ not much faster
+ quite possibly a performance regression due to lack of caching
+ More complex in overall system impact

Don
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,570
Members
45,045
Latest member
DRCM

Latest Threads

Top