From BRTT
Why do I get a segmentation fault when working with lists (Antelope's Tbl* objects)?
The Tbl utilities are Antelope's implementation of what would be called a "list" in the C++ stdlib. One of the big problems with list processing using this library is memory management. (The associative array utilities have similar caveats). This is, of course, a ubiquitous problem in C and and the reason that careless use of these utilities can cause a whole host of sometimes mysterious problems.
The problem that prompted me to write this is strtbl. strtbl
is a convenient mechanism to produce lists needed for functions
like dbmatches, but one must be VERY conscious that the following
are not at all equivalent:
Tbl t=strtbl("sta","chan","time",NULL):
versus
t=newtbl(0);
pushtbl(t,strdup("sta"));
pushtbl(t,strdup("chan"));
pushtbl(t,strdup("time"));
In the first case the strings "sta","chan", and "time"
are stored in static memory and will generate an error
if you try to free it with a call like
freetbl(t,free);
In contrast, this is exactly what you need to do for the
second case because strdup creates a copy of the three string
on the free store (or heap depending on what jargon you use
to refer to dynamically allocated data objects). In the
first case, you need to use a TRICK provided by in the tbl
interface wherein you should instead say:
freetbl(t,0);
This will free the space used to describe the list, but will not try to free the attached data objects.
If you use these functions incorrectly I have found the results can sometimes be mysterious. Usually the program will seg fault immediately when you call freetbl with the incorrect form, but I've also seen it do strange things and not cause a problem until downstream. It is the usual mystical problem of stray free calls to strange places. If you happen to point to a random place that you hadn't intended, good luck finding the error.
A good piece of practical advice on this point is to NEVER use strtbl to create a list used outside the scope of one function. If you intend to pass something back that includes a Tbl list, make sure you load the list with dynamically allocated objects from the free store. An equally stupid thing to do, by the way, could easily be committed by a beginner. You can create horrible chaos by pushing pointers to automatic variables in a function onto a list and trying to return the list. When the function goes out of scope these pointers can point at a random location that can lead to mysterious downstream errors.