SIGSEGV, not a problem just interesting observation.

Andries.Brouwer@cwi.nl (TIGRANA@DSTIUK.CCMAIL.CompuServe.COM)
23 May 97 09:52:37 EDT


Hi guys,

I would like to share with you a curious thing I have just noticed while
debugging my program that manipulates doubly-linked lists. The intersting fact
is that after I have tested the program successfully on DYNIX/ptx, Digital Unix
and IBM AIX I was almost confident that it works fine, but... as soon as I tried
it on Linux it mysteriously coredumped (with SIGSEGV). A few minutes of
debugging with gdb(1) revealed the following:

struct list {
char *text;
struct list *prev;
struct list *next;
};

In the 'traverse' function for doubly-linked list with first element pointed to
by 'root':

/* wrong version */
void traverselist(struct list *root, void (*visit)(struct list *p))
{
if (root != NULL) {
visit(root);
traverselist(root->next, visit);
}
}

/* correct version */
void traverselist(struct list *root, void (*visit)(struct list *p))
{
if (root != NULL) {
struct list *next = root->next;
visit(root);
traverselist(next, visit);
}
}

void freenode(struct list *node)
{
free(node->text);
free(node);
}

void freelist(struct list *root)
{
traverselist(root, freenode);
}

Now, when we invoke freelist() on ptx, AIX or Digital everything is fine, but on
Linux it coredumps as soon as root->next is referenced after call to visit(root)
because visit(root) destroyed the root so we shouldn't really reference it.

Thanks for your attention,
Tigran A. Aivazian.

PS. I know that linux-c-programming is more appropriate for this but recently it
was flooded with some rubbish by some idiot (lamer@aol.com) so I thought I would
wait a bit before sending or receiving anything from linux-c-programming.

PPS. If you have any comments please reply to me directly.