I was having a pretty productive day finding and fixing those two
arcane bugs, I gather :-) I'll commit them right away. Looking into
the array bounds problem is critical. Drew had some ideas about the
list.c implementation he considered rather obvious. I suppose that's
his inner teacher talking, leaving the actual solution to the
student....
All I can come up with is adding to list.c:105
tlist->start->nextnode=NULL;
so tlist->start is never without a nextnode field.
This is mandatory. You can't ever not do that. In fact, I consider it
best practice to do the following:
struct mystruct *ptr = (struct mystruct *)malloc(sizeof(struct
mystruct));
if (ptr != NULL) {
bzero(ptr, sizeof(struct mystruct));
/* Set initial/default values here if needed */
/* ptr->blah = foo; */
}
That way the entire contents of mystruct is zero'ed out in the event
that mystruct gets changed and a new member is added. I also wrap all
of these kinds of calls in functions so I can do something like:
struct mystruct* ptr = mystruct_new();
and not have to worry about chasing down all instances of malloc(3) to
adjust for code that changes.
Or better, fully initialize a struct element * before assigning it to
tlist->start.
How about:
struct element *new = (struct element *)my_malloc(sizeof(element));
new->data = (void *)my_malloc(dsize);
new->data = memcpy(new->data,data,dsize);
new->dsize = dsize;
new->nextnode = tlist->start;
tlist->start = new;
I left out the return value checks on the mallocs, for clarity sake.
Using the bzero(3) approach, plus setting the default values is the
best way to go.
/* Global context */
struct mystruct *list_ptr = NULL;
/* In a function: */
struct mystruct *ptr = mystruct_new();
/* Initialize ptr w/ the correct values, then call mystruct_prepend()
when you're ready to prepend it onto the list. */
mystruct_prepend(&list_ptr, ptr);
void
mystruct_prepend(struct mystruct **list, struct mystruct *elem) {
struct mystruct *tmp;
if (list == NULL)
return;
else if (*list == NULL)
*list = elem;
else {
elem->next = *list->head;
*list = elem;
}
}
How's that? This all being fine and well, I recommend making a copy of
and using the macros provided by sys/queue.h instead that way you can
get tail appends and never have to worry about uninitialized values or
bugs since these routines are well tested and fast (ie, they're used in
the kernel).
But I'm still unable to reproduce this bug, which makes it rather
difficult to track down.
Send me a patch, I can reproduce this problem in seconds with OS-X's
Mail.app. -sc
--
Sean Chittenden