3.4 Use of Memory
FunnelWeb is not a memory-stressed program. However, during its development, problems with the management of memory seemed to crop up again and again. This section documents some of these problems and the solutions that were adopted.
There are three places where memory can be obtained: the heap, the stack, and from static variables. The following three sections deal with each of these areas.
One of the great frustrations of being a user is to find that a computer program is complaining about lack of memory when one knows full well that one has allocated at least ten times as much memory to the program as it would ever need to do its job. The reason for such error messages usually has to do with the programmer setting a fixed "reasonable" limit to a particular data structure and then locking it up into an array whose bound is specified by a constant. This malody is particularly common in old Pascal programs. While the use of arrays can increase the speed of a program, it also means that the user cannot increase the capacity of the program without obtaining the source code and recompiling it.
The alternative is to use the heap for all data structures that can grow in proportion to the size of the user's input. This rule has been followed rigorously in FunnelWeb. This means that as memory spaces increase, users will be able to hand their version of FunnelWeb more memory without having to recompile it.
Some problems arose early on the Macintosh in the use of the heap. For some obscure reason, many of the heap application malloc calls were failing. Whatever it was, it went away when I replaced direct calls to malloc with calls to a mini package I wrote (called memory) that allocated large chunks of memory and then doled out small pieces as required by the rest of the program.
Having a package to manage all the memory allocation had two other benefits.
First, only one check was required in the entire program to see if memory had run out (in the memory package), and if that failed, the program could be brought to a screaming halt. This organization was far preferable to having each piece of code that needed to allocate memory having to check to see if malloc had failed.
Second, the decision to construct a mini-shell within FunnelWeb to support regression testing meant that FunnelWeb proper (the FunnelWeb fw shell command) could be run many times in any given invocation of FunnelWeb. As a consequence it was necessary to make sure that there was no memory leakage between invocations of FunnelWeb proper. This was accomplished by reworking the memory package to operate a watermark system. The user of the package, when requesting memory, could request "temporary" or "permanent". If permanent, the memory package forgot that it had allocated the memory. If temporary, the memory package places the allocated block on a list. There was then a function in the memory package that could be called to deallocate all the temporary memory. All this meant that so long as all requests for memory within FunnelWeb proper were for temporary memory, and that memory was freed at the end of every run, one could be sure that there was no memory leakage.
For a while during the development of FunnelWeb a particularly nasty bug proved extremely hard to find. The symptom was that FunnelWeb would crash, sometimes at random, but more often upon entering a particular function. In the end, about a day of specific debugging was required before the problem was tracked down to a stack problem. It turned out that somehow (either the fault of the Macintosh or the THINK C language system), the compiler was allocating just 6K for stack space!!!!!!!
This experience led me immediately to go through the entire program and eliminate (or remove to the heap) any automatic variable declarations that used more than one hundred or so bytes.
The lesson is clearly that C programs that use more than a few thousand bytes of stack space are risking their portability. All large data structures should be placed in the heap.
Static variables also proved a problem on the Macintosh. It turned out that the Macintosh THINK C compiler did not allow more than 32K of statics in the entire program . For a while this restriction was a serious threat to the program as it was discovered that constant strings were included in this total! However, some searching revealed a compiler option that removed the strings from the static category.
Nevertheless, the 32K limit is rather severe. Again, it seems that for portability reasons, C programs that use a lot of static variables are risking their portability. As a result, the FunnelWeb code avoids static variables where possible in favour of the heap.
Webmaster Copyright © Ross N. Williams 1992,1999. All rights reserved.