Hi,
the following is meant as a suggestion to be considered in conjunction
with general coding rules, if adequate. Don't feel urged to answer.
Some details may be somewhat incorrect for C++. Most of it is an
offspring from looking at those many implementation details in
figinset.C that I disliked.
PROBLEM
Possible heap corruption (rare cases, esp. when using fork()) or heap
overflow and heap fragmentation as well as relatively frequent memory
leaks when using 'new'/'delete' builtin operators or certain other
functions and programming techniques that employ dynamic memory.
Some of the problems I've seen with LyX inline image rendering may stem
from here. Even some sigsegvs with the new (old) 1.1.x may be related.
DESCRIPTION
"Behind the scenes" those operators eventually call malloc()/free()
library C fns (at least gcc/emx, but I think other compilers behave in
the same way). Similar problems occur with other functions employing
dynamic memory. This causes fragmentated memory and needs huge heap
sizes, so that hardware caching works inefficiently.
While on Unix-style OS the heap is allocated and re-sized
automatically on run-time, this is not true for other OS, where the
static heap (as well as the static executable stack) object is usually
sized and allocated only on compile time. In this way you can better
cope with hardware design restrictions because of limited hardware
memory, nowadays especially important to provide for efficient use of
the hardware cache. Drawback is that heap overflow is more likely to
happen compared to run-time heap management.
(EMX/gcc (with a grain of salt) uses both models, employing
a.out binaries in the former, OMF binaries in the latter case).
Both models have frequent problems with memory leaks if programs and
system libraries are not 100% bug-free. (Some special headaches/bugs
are caused by fork() emulation in conjunction with run-time re-sized
heaps.)
I found some *very* nice explanations of other concepts and related
bugs relevant in this context like 'stack frames', 'static memory',
which may be a possible solution to the described problems, by David
Evans/W.Sh. http://www.sds.lcs.mit.edu/~evs/pldi96-abstract.html), a
short excerpt of which I'm tempted to cite:
"Hamlet prefers garbage collection:
Yea, from the table of my memory I'll wipe away all trivial fond
records, all saws of books, all forms, all pressures past, that youth
and observation copied there.
(Shakespeare, Hamlet. Act I, Scene v)
Ophelia prefers explicit deallocation:
`Tis in my memory lock'd, and you yourself shall keep the key of it.
(Hamlet. Act I, Scene iii)
Local variables that are not allocated dynamically are stored on a
call stack. When a function returns, its stack frame is deallocated,
destroying the storage associated with the function's local variables.
A memory error occurs if a pointer into this storage is live after
the function returns (involving stack references exported from a
function through return values or assignments to references reachable
from global variables or actual parameters).
In a garbage-collected environment, there may be storage that is shared
by one or more references and never explicitly released.
All obligations to release storage stem from primitive allocation
routines (e.g.,malloc), and are ultimately satisfied by calls to free()
(According to [ANSI, 4.10.3.2], NULL may be passed to free
without an error. On some UNIX platforms, passing NULL to free causes a
program crash.);
the argument may be NULL and need not point to defined storage. The
parameter to free must reference an unshared object, the caller may
not use the referenced object after the call, and may not pass in
a reference to a shared object."
POSSIBLE SOLUTIONS
Try to use small and better maintainable "static inline" functions
allocating memory objects only on their stack frame, i.e. using
variables local to them, consistently avoiding 'new'/'delete'. Thus
memory remains confined within block nesting and exists only during
block life time. This should reduce most problems described at the
beginning.
Use preferably "alloc"-style garbage collection avoiding explicit
memory deallocation ("delete"/"free()") if this is possible.
I've no proposal for global linked list-type objects that need dynamic
memory :(.
Greets,
Arnd
PS: Does a tool like 'lclint' exist for C++?